Merged Ombase's changes.
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 113 KiB |
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Td from "./Td";
|
import Td from "./Td";
|
||||||
import Laoder from "./Laoder";
|
import Loader from "./Loader";
|
||||||
|
|
||||||
const FarmList = () => {
|
const FarmList = () => {
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
@@ -19,7 +19,7 @@ const FarmList = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
|
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Laoder></Laoder>
|
<Loader></Loader>
|
||||||
) : (
|
) : (
|
||||||
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const Laoder = () => {
|
const Loader = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full bg-white rounded-lg shadow p-4">
|
<div className="w-full bg-white rounded-lg shadow p-4">
|
||||||
<div class="flex items-center justify-center w-full h-56 border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
|
<div class="flex items-center justify-center w-full h-56 border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
|
||||||
@@ -26,4 +26,4 @@ const Laoder = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Laoder;
|
export default Loader;
|
||||||
@@ -6,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">
|
||||||
100,000
|
₹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
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const Piechart = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="bg-white md:p-6 block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
<div className="bg-white md:p-6 block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
||||||
<h5 className="text-xl font-bold text-gray-900 dark:text-white mb-4 ">
|
<h5 className="text-xl font-bold text-gray-900 dark:text-white mb-4 ">
|
||||||
Cost Analysis
|
Farm Info
|
||||||
</h5>
|
</h5>
|
||||||
<Chart options={chartOptions} series={series} type="donut" height={320} />
|
<Chart options={chartOptions} series={series} type="donut" height={320} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ import Monitoring from "./pages/UserPanel/Monitoring.jsx";
|
|||||||
import AddFarm from "./pages/UserPanel/Farm/AddFarm.jsx";
|
import AddFarm from "./pages/UserPanel/Farm/AddFarm.jsx";
|
||||||
import UpdateFarm from "./pages/UserPanel/Farm/UpdateForm.jsx";
|
import UpdateFarm from "./pages/UserPanel/Farm/UpdateForm.jsx";
|
||||||
import FarmPage from "./pages/UserPanel/Farm/FarmPage.jsx";
|
import FarmPage from "./pages/UserPanel/Farm/FarmPage.jsx";
|
||||||
|
import Ai from "./pages/UserPanel/Ai.jsx";
|
||||||
createRoot(document.getElementById("root")).render(
|
createRoot(document.getElementById("root")).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<Provider store={MentifyStore}>
|
<Provider store={MentifyStore}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Routes>
|
<Routes>
|
||||||
|
<Route path="/ai" element={<Ai />} />
|
||||||
{/* Routes for the main App */}
|
{/* Routes for the main App */}
|
||||||
<Route path="/" element={<App />}>
|
<Route path="/" element={<App />}>
|
||||||
<Route index element={<HomePage />} />
|
<Route index element={<HomePage />} />
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
const Ai = () => {
|
||||||
|
const [selectedFile, setSelectedFile] = useState(null);
|
||||||
|
const [prediction, setPrediction] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
const handleFileChange = (e) => {
|
||||||
|
if (e.target.files && e.target.files[0]) {
|
||||||
|
setSelectedFile(e.target.files[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!selectedFile) return;
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
setPrediction("");
|
||||||
|
setError("");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("image", selectedFile);
|
||||||
|
|
||||||
|
const response = await fetch("http://localhost:3000/predict", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Prediction request failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
// Assuming the API returns a JSON object with an "output" field.
|
||||||
|
setPrediction(data.output || "No prediction returned");
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error during prediction:", err);
|
||||||
|
setError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="max-w-md mx-auto p-6 bg-white shadow rounded-lg">
|
||||||
|
<h2 className="text-2xl font-bold mb-4 text-center">
|
||||||
|
Plant disease prediction
|
||||||
|
</h2>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
onChange={handleFileChange}
|
||||||
|
className="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 p-2"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading || !selectedFile}
|
||||||
|
className="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
>
|
||||||
|
{loading ? "Predicting..." : "Predict"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{error && <p className="mt-4 text-center text-red-600">{error}</p>}
|
||||||
|
{prediction && (
|
||||||
|
<div className="mt-4 p-4 bg-green-100 border border-green-300 rounded">
|
||||||
|
<h3 className="text-lg font-semibold">Prediction:</h3>
|
||||||
|
<p>{prediction}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Ai;
|
||||||
@@ -12,7 +12,7 @@ const Dashboard = () => {
|
|||||||
<AddFarm />
|
<AddFarm />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4 flex space-x-4">
|
<div className="mb-4 flex space-x-10">
|
||||||
<Piechart />
|
<Piechart />
|
||||||
<TotalSpent />
|
<TotalSpent />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
|
const AddTransaction = ({ farmId }) => {
|
||||||
|
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 handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
setMessage("");
|
||||||
|
|
||||||
|
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,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to create transaction");
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Transaction created:", data);
|
||||||
|
setMessage("Transaction created successfully!");
|
||||||
|
// Optionally clear the form
|
||||||
|
setType("Expense");
|
||||||
|
setAmount("");
|
||||||
|
setDescription("");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating transaction:", error);
|
||||||
|
setMessage("Error creating transaction.");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => setModalOpen(true)}
|
||||||
|
className="block text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Add Transaction
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{modalOpen && (
|
||||||
|
<div className="fixed inset-0 z-50 flex justify-center items-center overflow-y-auto overflow-x-hidden bg-black bg-opacity-50">
|
||||||
|
<div className="relative p-4 w-full max-w-md">
|
||||||
|
<div className="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||||
|
{/* Modal Header */}
|
||||||
|
<div className="flex justify-between items-center p-4 border-b rounded-t dark:border-gray-600">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||||
|
Add Transaction
|
||||||
|
</h3>
|
||||||
|
<button
|
||||||
|
onClick={() => setModalOpen(false)}
|
||||||
|
type="button"
|
||||||
|
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-5 h-5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M6 18L18 6M6 6l12 12"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/* Modal Body */}
|
||||||
|
<div className="p-4">
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="transaction-type"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="transaction-type"
|
||||||
|
value={type}
|
||||||
|
onChange={(e) => setType(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="Expense">Expense</option>
|
||||||
|
<option value="Revenue">Revenue</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="transaction-amount"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Amount
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="transaction-amount"
|
||||||
|
value={amount}
|
||||||
|
onChange={(e) => setAmount(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="transaction-description"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="transaction-description"
|
||||||
|
value={description}
|
||||||
|
onChange={(e) => setDescription(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
>
|
||||||
|
{loading ? <Loader></Loader> : "Add Transaction"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{message && (
|
||||||
|
<p className="mt-4 text-sm text-center text-green-600">
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddTransaction;
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
const CreateTask = ({ farmId, onTaskCreated }) => {
|
||||||
|
const [farm, setFarm] = useState(farmId);
|
||||||
|
const [taskType, setTaskType] = useState("Sowing");
|
||||||
|
const [description, setDescription] = useState("Started Sowing the seeds");
|
||||||
|
const [assignedDate, setAssignedDate] = useState("2025-04-15");
|
||||||
|
const [status, setStatus] = useState("Pending");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [message, setMessage] = useState("");
|
||||||
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
setMessage("");
|
||||||
|
|
||||||
|
// In a real app, you might also fetch or choose a crop.
|
||||||
|
// For now, we assume crop is provided.
|
||||||
|
const crop = "67ba388f9c4979463e64a39a";
|
||||||
|
const taskData = {
|
||||||
|
farm,
|
||||||
|
crop,
|
||||||
|
taskType,
|
||||||
|
description,
|
||||||
|
assignedDate,
|
||||||
|
status,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("http://localhost:8000/api/v1/task", {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(taskData),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to create task");
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Task created:", data);
|
||||||
|
setMessage("Task created successfully!");
|
||||||
|
setModalOpen(false);
|
||||||
|
// Call the parent's callback with the newly created task
|
||||||
|
if (onTaskCreated) onTaskCreated(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating task:", error);
|
||||||
|
setMessage("Error creating task.");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => setModalOpen(true)}
|
||||||
|
className="block text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Create Task
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{modalOpen && (
|
||||||
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-75">
|
||||||
|
<div className="relative w-full max-w-2xl p-6 bg-white rounded-lg shadow-xl">
|
||||||
|
<div className="flex justify-between items-center border-b pb-3">
|
||||||
|
<h2 className="text-2xl font-bold text-gray-800">Create Task</h2>
|
||||||
|
<button
|
||||||
|
onClick={() => setModalOpen(false)}
|
||||||
|
type="button"
|
||||||
|
className="text-gray-600 hover:text-gray-800"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="h-6 w-6"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M6 18L18 6M6 6l12 12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="task-type"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Task Type
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="task-type"
|
||||||
|
value={taskType}
|
||||||
|
onChange={(e) => setTaskType(e.target.value)}
|
||||||
|
className="mt-2 block w-full rounded-md border-gray-300 shadow-sm p-3 focus:ring-2 focus:ring-green-400"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="Sowing">Sowing</option>
|
||||||
|
<option value="Watering">Watering</option>
|
||||||
|
<option value="Fertilization">Fertilization</option>
|
||||||
|
<option value="Pest Control">Pest Control</option>
|
||||||
|
<option value="Harvesting">Harvesting</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="description"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="description"
|
||||||
|
value={description}
|
||||||
|
onChange={(e) => setDescription(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="assignedDate"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Assigned Date
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
id="assignedDate"
|
||||||
|
value={assignedDate}
|
||||||
|
onChange={(e) => setAssignedDate(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="status"
|
||||||
|
className="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Status
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="status"
|
||||||
|
value={status}
|
||||||
|
onChange={(e) => setStatus(e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="Pending">Pending</option>
|
||||||
|
<option value="Completed">Completed</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full inline-flex justify-center py-2 px-4 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
>
|
||||||
|
{loading ? "Creating Task..." : "Create Task"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{message && (
|
||||||
|
<p className="mt-4 text-center text-sm text-green-600">
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateTask;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Laoder from "../../../components/Laoder";
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
const CreateFinance = () => {
|
const CreateFinance = () => {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -34,17 +34,13 @@ const CreateFinance = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-md mx-auto p-4 border rounded shadow">
|
|
||||||
<h2 className="text-xl font-bold mb-4">Create Finance</h2>
|
|
||||||
<button
|
<button
|
||||||
onClick={handleCreateFinance}
|
onClick={handleCreateFinance}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="mt-4 w-full inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
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 ? <Laoder></Laoder> : "Create Finance"}
|
{loading ? <Loader></Loader> : "Create Finance"}
|
||||||
</button>
|
</button>
|
||||||
{message && <p className="mt-4 text-sm text-green-600">{message}</p>}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Laoder from "../../../components/Laoder";
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
const CropTable = ({ farmId }) => {
|
const CropTable = ({ farmId }) => {
|
||||||
const [crops, setCrops] = useState([]);
|
const [crops, setCrops] = useState([]);
|
||||||
@@ -49,7 +49,7 @@ const CropTable = ({ farmId }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Laoder></Laoder>;
|
return <Loader></Loader>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
|
const DisplayTast = ({ farmId }) => {
|
||||||
|
const [tasks, setTasks] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
// Function to delete a task and update the state
|
||||||
|
const handleDeleteTask = async (taskId) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`http://localhost:8000/api/v1/task/${taskId}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// Assuming that a successful deletion returns a 200 status code
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to delete task");
|
||||||
|
}
|
||||||
|
// Optionally check the response, but we'll update state regardless.
|
||||||
|
// Remove the deleted task from state.
|
||||||
|
setTasks((prevTasks) => prevTasks.filter((task) => task._id !== taskId));
|
||||||
|
console.log(`Task ${taskId} deleted successfully.`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting task:", error);
|
||||||
|
// Optionally, you could set an error state here.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchTasks = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`http://localhost:8000/api/v1/task/farm/${farmId}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch tasks");
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
setTasks(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchTasks();
|
||||||
|
}, [farmId]);
|
||||||
|
|
||||||
|
if (loading) return <div>Loading tasks...</div>;
|
||||||
|
if (error) return <div className="text-red-600">Error: {error}</div>;
|
||||||
|
if (!tasks || tasks.length === 0) {
|
||||||
|
return <div className="p-4">No tasks found for this farm.</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="overflow-x-auto w-full p-4">
|
||||||
|
<table className="w-full text-sm text-left border">
|
||||||
|
<thead className="text-xs text-gray-700 uppercase bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<th className="px-6 py-3">Task Type</th>
|
||||||
|
<th className="px-6 py-3">Description</th>
|
||||||
|
<th className="px-6 py-3">Assigned Date</th>
|
||||||
|
<th className="px-6 py-3">Status</th>
|
||||||
|
<th className="px-6 py-3">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{tasks.map((task) => (
|
||||||
|
<tr key={task._id} className="bg-white border-b hover:bg-gray-50">
|
||||||
|
<td className="px-6 py-4">{task.taskType}</td>
|
||||||
|
<td className="px-6 py-4">{task.description}</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
{new Date(task.assignedDate).toLocaleDateString()}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4">{task.status}</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
<button
|
||||||
|
onClick={() => handleDeleteTask(task._id)}
|
||||||
|
className="block text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DisplayTast;
|
||||||
@@ -48,7 +48,9 @@ const Farm = ({ farmData, farmId }) => {
|
|||||||
<td className="px-6 py-4">{farmData.soilType}</td>
|
<td className="px-6 py-4">{farmData.soilType}</td>
|
||||||
<td className="px-6 py-4">{farmData.size}</td>
|
<td className="px-6 py-4">{farmData.size}</td>
|
||||||
<td className="px-6 py-4">{farmData.waterContent}</td>
|
<td className="px-6 py-4">{farmData.waterContent}</td>
|
||||||
<td className="px-6 py-4">Edit</td>
|
<td className="px-6 py-4">
|
||||||
|
<EditFarm></EditFarm>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import Farm from "./Farm";
|
|||||||
import CropTable from "./CropTable";
|
import CropTable from "./CropTable";
|
||||||
import Transactions from "./Transactions";
|
import Transactions from "./Transactions";
|
||||||
import CreateTransactions from "./CreateTransactions";
|
import CreateTransactions from "./CreateTransactions";
|
||||||
import Laoder from "../../../components/Laoder";
|
import Loader from "../../../components/Loader";
|
||||||
|
import AddTransaction from "./AddTransactions";
|
||||||
|
import FinanceSummary from "./FinanceSummary";
|
||||||
|
import CreateTask from "./CreateTask";
|
||||||
|
import DisplayTast from "./DisplayTask";
|
||||||
|
|
||||||
export default function FarmPage() {
|
export default function FarmPage() {
|
||||||
const { farmId } = useParams();
|
const { farmId } = useParams();
|
||||||
@@ -13,7 +17,7 @@ export default function FarmPage() {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetching() {
|
async function fetchFarmData() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`http://localhost:8000/api/v1/farm/${farmId}`,
|
`http://localhost:8000/api/v1/farm/${farmId}`,
|
||||||
@@ -26,7 +30,7 @@ export default function FarmPage() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const jsonData = await response.json();
|
const jsonData = await response.json();
|
||||||
console.log(jsonData);
|
console.log("Fetched farm data:", jsonData);
|
||||||
setFarmData(jsonData);
|
setFarmData(jsonData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching farm data: ", error);
|
console.error("Error fetching farm data: ", error);
|
||||||
@@ -34,11 +38,11 @@ export default function FarmPage() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fetching();
|
fetchFarmData();
|
||||||
}, [farmId]);
|
}, [farmId]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Laoder></Laoder>;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!farmData) {
|
if (!farmData) {
|
||||||
@@ -49,24 +53,59 @@ export default function FarmPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("My farm id is : ", farmId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full bg-white rounded-lg shadow p-4">
|
<div className="w-full bg-white rounded-lg shadow p-4 space-y-8">
|
||||||
{/* Back Button */}
|
{/* Header Section */}
|
||||||
|
<header className="mb-4">
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Farm farmData={farmData} farmId={farmId} />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div className="mb-4 flex justify-end">
|
{/* Crop Table Section */}
|
||||||
<Farm farmData={farmData} farmId={farmId}></Farm>
|
<section>
|
||||||
|
<CropTable farmId={farmId} />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Create Transactions Section */}
|
||||||
|
<section>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<CreateTransactions farmId={farmId} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4 ">
|
</section>
|
||||||
<CropTable farmId={farmId}></CropTable>
|
|
||||||
|
{/* Transactions Table Section */}
|
||||||
|
<section>
|
||||||
|
<Transactions farmId={farmId} />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Add Transaction Modal Section */}
|
||||||
|
<section>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<AddTransaction farmId={farmId} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4 flex justify-end">
|
</section>
|
||||||
<CreateTransactions farmId={farmId}></CreateTransactions>
|
|
||||||
|
{/* Finance Summary Section */}
|
||||||
|
<section>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<FinanceSummary farmId={farmId} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4 ">
|
</section>
|
||||||
<Transactions farmId={farmId}></Transactions>
|
|
||||||
|
{/* Create Task Section */}
|
||||||
|
<section>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<CreateTask farmId={farmId} />
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Display Task Section */}
|
||||||
|
<section>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<DisplayTast farmId={farmId} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
|
const FinanceSummary = ({ farmId }) => {
|
||||||
|
const [summary, setSummary] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSummary = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
setError("");
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`http://localhost:8000/api/v1/finance/summary/${farmId}`,
|
||||||
|
{ credentials: "include" }
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch summary");
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
setSummary(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching finance summary:", err);
|
||||||
|
setError("Error fetching summary");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchSummary();
|
||||||
|
}, [farmId]);
|
||||||
|
|
||||||
|
if (loading) return <Loader />;
|
||||||
|
if (error) return <div className="p-4 text-center text-red-600">{error}</div>;
|
||||||
|
|
||||||
|
// Extract only the important fields.
|
||||||
|
const { totalExpenses, totalRevenue, transactions } = summary;
|
||||||
|
const transactionsCount = Array.isArray(transactions)
|
||||||
|
? transactions.length
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="max-w-md 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>
|
||||||
|
</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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FinanceSummary;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Td from "../../../components/Td";
|
import Td from "../../../components/Td";
|
||||||
import Laoder from "../../../components/Laoder";
|
import Loader from "../../../components/Loader";
|
||||||
|
|
||||||
const Transactions = ({ farmId }) => {
|
const Transactions = ({ farmId }) => {
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
@@ -25,34 +25,36 @@ const Transactions = ({ farmId }) => {
|
|||||||
return (
|
return (
|
||||||
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
|
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Laoder></Laoder>
|
<Loader />
|
||||||
) : (
|
) : (
|
||||||
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" className="px-6 py-3">
|
<th scope="col" className="px-6 py-3">
|
||||||
Farm name
|
Field
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" className="px-6 py-3">
|
<th scope="col" className="px-6 py-3">
|
||||||
Location
|
Value
|
||||||
</th>
|
|
||||||
<th scope="col" className="px-6 py-3">
|
|
||||||
Type
|
|
||||||
</th>
|
|
||||||
<th scope="col" className="px-6 py-3">
|
|
||||||
Size (acres)
|
|
||||||
</th>
|
|
||||||
<th scope="col" className="px-6 py-3">
|
|
||||||
Action
|
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{Array.isArray(data) && data.length > 0 ? (
|
{!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} />)
|
data.map((item) => <Td key={item.id} children={item} />)
|
||||||
) : (
|
) : (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={5} className="text-center">
|
<td colSpan={2} className="text-center">
|
||||||
No data available
|
No data available
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const MainUserPanel = () => {
|
|||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
{/* <li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/scheduledmeetings"}
|
to={"/user/dashboard/scheduledmeetings"}
|
||||||
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
||||||
@@ -81,7 +81,7 @@ const MainUserPanel = () => {
|
|||||||
Scheduled Meeting
|
Scheduled Meeting
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li> */}
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/monitoring"}
|
to={"/user/dashboard/monitoring"}
|
||||||
@@ -93,7 +93,7 @@ const MainUserPanel = () => {
|
|||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
{/* <li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/notifications"}
|
to={"/user/dashboard/notifications"}
|
||||||
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
||||||
@@ -103,8 +103,8 @@ const MainUserPanel = () => {
|
|||||||
Notifications
|
Notifications
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li> */}
|
||||||
<li>
|
{/* <li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/feedback"}
|
to={"/user/dashboard/feedback"}
|
||||||
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
||||||
@@ -115,7 +115,8 @@ const MainUserPanel = () => {
|
|||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
*/}
|
||||||
|
{/* <li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/support"}
|
to={"/user/dashboard/support"}
|
||||||
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
className="flex items-center p-2 rounded-md hover:bg-green-100/30 transition-colors backdrop-blur-md"
|
||||||
@@ -126,6 +127,7 @@ const MainUserPanel = () => {
|
|||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
*/}
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<Link
|
||||||
to={"/user/dashboard/settings"}
|
to={"/user/dashboard/settings"}
|
||||||
@@ -240,8 +242,7 @@ const MainUserPanel = () => {
|
|||||||
Join on {user.createdAt && user.createdAt.substring(0, 10)}
|
Join on {user.createdAt && user.createdAt.substring(0, 10)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-gray-500 text-sm mt-2">
|
<p className="text-gray-500 text-sm mt-2">
|
||||||
{user.description == null &&
|
{user.address == null && "Maharashtra, Pune"}
|
||||||
"I am a Senior Software Engineer at Google and also mentored 50+ students to get their dream job."}
|
|
||||||
</p>
|
</p>
|
||||||
<div className="flex justify-center mt-4">
|
<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">
|
<button className="bg-gray-300 hover:bg-gray-400 text-gray-700 font-bold py-2 px-4 rounded mr-2">
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Reference in New Issue
Block a user