diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 275a361..731dbab 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -5,9 +5,3 @@
**If your issue was not created using the app above, it will be closed immediately.**
-->
-
-
diff --git a/src/api/ManageUser/users.js b/src/api/ManageUser/users.js
new file mode 100644
index 0000000..7abc093
--- /dev/null
+++ b/src/api/ManageUser/users.js
@@ -0,0 +1,52 @@
+import axios from "axios";
+import baseURL from "config";
+
+// Function to delete a user
+export async function deleteUser(userId) {
+ try {
+ const response = await axios.post(`${baseURL}/delete-user`, { user_ID: userId });
+ if (response.status === 200) {
+ console.log(response.data.message); // Assuming the response has a message field
+ } else {
+ console.error("Failed to delete user:", response.statusText);
+ }
+ } catch (error) {
+ console.error("Error deleting user:", error);
+ throw error;
+ }
+}
+
+// Function to edit user details
+export async function editUser(userId, updatedData) {
+ try {
+ const response = await axios.post(`${baseURL}/updateUser`, {
+ userId: userId,
+ fullName: updatedData.fullName,
+ mobile: updatedData.contactNumber,
+ profession: updatedData.profession,
+ });
+ if (response.status === 200) {
+ console.log(response.data.message); // Assuming the response has a message field
+ } else {
+ console.error("Failed to edit user:", response.statusText);
+ }
+ } catch (error) {
+ console.error("Error editing user:", error);
+ throw error;
+ }
+}
+
+// Function to get the list of users
+export async function getUserList() {
+ try {
+ const response = await axios.get(`${baseURL}/getAllUsers`);
+ if (response.status === 200) {
+ return response.data;
+ } else {
+ console.error("Failed to fetch user list:", response.statusText);
+ }
+ } catch (error) {
+ console.error("Error fetching user list:", error);
+ throw error;
+ }
+}
diff --git a/src/api/sendImg.js b/src/api/advertisementextract/sendImg.js
similarity index 100%
rename from src/api/sendImg.js
rename to src/api/advertisementextract/sendImg.js
diff --git a/src/api/sendPdf.js b/src/api/advertisementextract/sendPdf.js
similarity index 100%
rename from src/api/sendPdf.js
rename to src/api/advertisementextract/sendPdf.js
diff --git a/src/api/sendUrl.js b/src/api/advertisementextract/sendUrl.js
similarity index 80%
rename from src/api/sendUrl.js
rename to src/api/advertisementextract/sendUrl.js
index 186d58e..9a455c0 100644
--- a/src/api/sendUrl.js
+++ b/src/api/advertisementextract/sendUrl.js
@@ -2,14 +2,14 @@
import baseURL from "config";
-export async function sendUrlToBackend(inputUrl) {
+export async function sendUrlToBackend(inputUrl, publish) {
try {
const response = await fetch(`${baseURL}/sendurl`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
- body: JSON.stringify({ url: inputUrl }),
+ body: JSON.stringify({ url: inputUrl, publish: publish }),
});
if (!response.ok) {
diff --git a/src/api/graphViewer/prediction.js b/src/api/graphViewer/prediction.js
new file mode 100644
index 0000000..8bb6eb5
--- /dev/null
+++ b/src/api/graphViewer/prediction.js
@@ -0,0 +1,13 @@
+import axios from "axios";
+import baseURL from "config";
+
+// Function to fetch data from the backend
+export async function getPriceFluct() {
+ try {
+ const response = await axios.get(`${baseURL}/priceFluctuationData`); // Adjust the endpoint URL
+ return response.data;
+ } catch (error) {
+ console.error("Error fetching data from the backend:", error);
+ throw error;
+ }
+}
diff --git a/src/api/pendingAdvertisement/pendingAdvertisemnet.js b/src/api/pendingAdvertisement/pendingAdvertisemnet.js
new file mode 100644
index 0000000..39bd37a
--- /dev/null
+++ b/src/api/pendingAdvertisement/pendingAdvertisemnet.js
@@ -0,0 +1,12 @@
+import axios from "axios";
+import baseURL from "config";
+
+export async function fetchPendingAdvertisements() {
+ try {
+ const response = await axios.get(`${baseURL}/pendingAdvertisements`); // Adjust the endpoint URL
+ return response.data;
+ } catch (error) {
+ console.error("Error fetching pending advertisements:", error);
+ throw error;
+ }
+}
diff --git a/src/api/report/getReports.js b/src/api/report/getReports.js
index 179dbc9..1bbb9b0 100644
--- a/src/api/report/getReports.js
+++ b/src/api/report/getReports.js
@@ -1,25 +1,47 @@
import axios from "axios";
import baseURL from "config";
-// Function to fetch a saved PDF report from the backend
-export async function getReportPdf(reportId) {
+// Function to delete a user
+export async function deleteUser(userId) {
try {
- const response = await axios.get(`${baseURL}/view-pdf?ReportID=${reportId}`, {
- responseType: "blob", // Specify the response type as a blob
- });
+ const response = await axios.delete(`${baseURL}/users/${userId}`);
+ if (response.status === 200) {
+ console.log(`User with ID ${userId} has been deleted`);
+ } else {
+ console.error("Failed to delete user:", response.statusText);
+ }
+ } catch (error) {
+ console.error("Error deleting user:", error);
+ throw error;
+ }
+}
+// Function to edit user details
+export async function editUser(userId, updatedData) {
+ try {
+ const response = await axios.put(`${baseURL}/users/${userId}`, updatedData);
if (response.status === 200) {
- // Create a blob URL for the PDF data
- const blob = new Blob([response.data], { type: "application/pdf" });
- const url = window.URL.createObjectURL(blob);
+ console.log(`User with ID ${userId} has been updated`);
+ } else {
+ console.error("Failed to edit user:", response.statusText);
+ }
+ } catch (error) {
+ console.error("Error editing user:", error);
+ throw error;
+ }
+}
- // Open the PDF in a new tab
- window.open(url, "_blank");
+// Function to get the list of users
+export async function getUserList() {
+ try {
+ const response = await axios.get(`${baseURL}/users`);
+ if (response.status === 200) {
+ return response.data;
} else {
- console.error("Failed to fetch PDF report:", response.statusText);
+ console.error("Failed to fetch user list:", response.statusText);
}
} catch (error) {
- console.error("Error fetching PDF report:", error);
+ console.error("Error fetching user list:", error);
throw error;
}
}
diff --git a/src/api/submitAdvertisement/submitAdvertisement.js b/src/api/submitAdvertisement/submitAdvertisement.js
new file mode 100644
index 0000000..86b5ea9
--- /dev/null
+++ b/src/api/submitAdvertisement/submitAdvertisement.js
@@ -0,0 +1,13 @@
+import axios from "axios";
+import baseURL from "config";
+
+export async function submitAdvertisement(formData) {
+ console.log("submitAdvertisement formData:", formData);
+ try {
+ const response = await axios.post(`${baseURL}/submitAdvertisement`, formData); // Adjust the endpoint URL
+ return response.data;
+ } catch (error) {
+ console.error("Error submitting advertisement:", error);
+ throw error;
+ }
+}
diff --git a/src/api/updateUser/updateUser.js b/src/api/updateUser/updateUser.js
index b0873a9..35af6ca 100644
--- a/src/api/updateUser/updateUser.js
+++ b/src/api/updateUser/updateUser.js
@@ -12,3 +12,33 @@ export async function updateUser(userData) {
throw error;
}
}
+
+export async function updateProfilePicture(url, userId) {
+ try {
+ const response = await axios.post(`${baseURL}/updateProfilePicture`, { url, userId }); // Adjust the endpoint URL
+ console.log(response.data);
+ return response.data;
+ } catch (error) {
+ console.error("Error updating user data on the backend:", error);
+ throw error;
+ }
+}
+
+export async function updateLastSeen(userid) {
+ try {
+ const last_seen = Date.now(); // Obtain the timestamp
+ const date = new Date(last_seen); // Convert the timestamp to a Date object
+ const lastSeenDate = date.toLocaleDateString(); // Obtain the date in a locale-specific format
+ const lastSeenTime = date.toLocaleTimeString(); // Obtain the time in a locale-specific format
+ const lastSeenDateTime = `${lastSeenDate} ${lastSeenTime}`; // Combine the date and time
+ console.log(userid, lastSeenDateTime);
+ const response = await axios.post(`${baseURL}/updateLastSeen`, {
+ last_seen: lastSeenDateTime,
+ userId: userid,
+ });
+ return response.data;
+ } catch (error) {
+ console.error("Error updating user data on the backend:", error);
+ throw error;
+ }
+}
diff --git a/src/assets/images/newsback.jpg b/src/assets/images/newsback.jpg
new file mode 100644
index 0000000..bdab124
Binary files /dev/null and b/src/assets/images/newsback.jpg differ
diff --git a/src/examples/Cards/InfoCards/ProfileInfoCard/index.js b/src/examples/Cards/InfoCards/ProfileInfoCard/index.js
index 04df700..f5fd122 100644
--- a/src/examples/Cards/InfoCards/ProfileInfoCard/index.js
+++ b/src/examples/Cards/InfoCards/ProfileInfoCard/index.js
@@ -34,6 +34,7 @@ import colors from "assets/theme/base/colors";
import typography from "assets/theme/base/typography";
import UpdateInfoModal from "./updateInfo";
import { useState } from "react";
+import MDAlert from "components/MDAlert";
function ProfileInfoCard({ title, description, info, social, action, shadow }) {
const labels = [];
@@ -88,6 +89,7 @@ function ProfileInfoCard({ title, description, info, social, action, shadow }) {
));
const [isModalOpen, setIsModalOpen] = useState(false);
+ const [isPasswordChanged, setIsPasswordChanged] = useState(false);
const handleOpenModal = () => {
setIsModalOpen(true);
@@ -105,6 +107,11 @@ function ProfileInfoCard({ title, description, info, social, action, shadow }) {
return (
+ {isPasswordChanged && (
+
+ Your password have been changed
+
+ )}
{title}
@@ -119,6 +126,7 @@ function ProfileInfoCard({ title, description, info, social, action, shadow }) {
onClose={handleCloseModal}
onSave={handleSaveInfo}
initialValues={updatedInfo} // Pass the current info data as initialValues
+ setChangePassword={setIsPasswordChanged}
/>
diff --git a/src/examples/Cards/InfoCards/ProfileInfoCard/updateInfo.js b/src/examples/Cards/InfoCards/ProfileInfoCard/updateInfo.js
index 0ab3047..05fac49 100644
--- a/src/examples/Cards/InfoCards/ProfileInfoCard/updateInfo.js
+++ b/src/examples/Cards/InfoCards/ProfileInfoCard/updateInfo.js
@@ -11,8 +11,9 @@ import MDButton from "components/MDButton";
import { updateUser } from "api/updateUser/updateUser";
import { useUser } from "utils/userContext";
-function UpdateInfoModal({ open, onClose, onSave, initialValues }) {
+function UpdateInfoModal({ open, onClose, onSave, initialValues, setChangePassword }) {
const [formData, setFormData] = useState(initialValues);
+ // const [changePassword, setChangePassword] = useState(false); // State to hold the change password checkbox value
const { user } = useUser();
const handleInputChange = (e) => {
@@ -24,13 +25,23 @@ function UpdateInfoModal({ open, onClose, onSave, initialValues }) {
};
const handleSave = async () => {
- onSave(formData);
+ // eslint-disable-next-line no-unused-vars
+ const { password, ...formDataToSave } = formData;
+ onSave(formDataToSave);
+
try {
const userId = user.user_ID; // Extract the user ID from the form data
- const { fullName, mobile, profession, location } = formData;
+ const { fullName, mobile, profession, location, password } = formData;
console.log(formData);
- const userData = { fullName, mobile, profession, location, userId };
- await updateUser(userData); // Call the updateUser API function
+ const userData = { fullName, mobile, profession, location, password, userId };
+ const response = await updateUser(userData); // Call the updateUser API function
+
+ // Check if the password was updated
+ if (response && response.password_updated) {
+ setChangePassword(true); // Reset the change password checkbox
+ // You can use a state or a notification library here to show the message to the user
+ console.log("Password has been updated.");
+ }
onClose(); // Close the modal after the update is successful
} catch (error) {
@@ -93,6 +104,23 @@ function UpdateInfoModal({ open, onClose, onSave, initialValues }) {
{/* Add more fields as needed */}
+
+
+ Change Account Password
+
+
+
+
+
Save
@@ -114,6 +142,7 @@ UpdateInfoModal.propTypes = {
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
initialValues: PropTypes.object.isRequired,
+ setChangePassword: PropTypes.func.isRequired,
};
export default UpdateInfoModal;
diff --git a/src/examples/Cards/ProjectCards/DefaultProjectCard/index.js b/src/examples/Cards/ProjectCards/DefaultProjectCard/index.js
index 3f7c523..8ad5f03 100644
--- a/src/examples/Cards/ProjectCards/DefaultProjectCard/index.js
+++ b/src/examples/Cards/ProjectCards/DefaultProjectCard/index.js
@@ -30,6 +30,7 @@ import MDTypography from "components/MDTypography";
import MDButton from "components/MDButton";
import MDAvatar from "components/MDAvatar";
import { useRef, useState, useEffect } from "react";
+import { Box } from "@mui/material";
function DefaultProjectCard({ image, label, title, description, action, authors }) {
const renderAuthors = authors.map(({ image: media, name }) => (
@@ -94,30 +95,44 @@ function DefaultProjectCard({ image, label, title, description, action, authors
}}
>
- md,
- objectFit: "cover",
- objectPosition: "center",
- }}
- />
+
+ md,
+ objectFit: "cover",
+ objectPosition: "center",
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ }}
+ />
+
+
{label}
-
+
{action.type === "internal" ? (
{title}
@@ -129,13 +144,29 @@ function DefaultProjectCard({ image, label, title, description, action, authors
rel="noreferrer"
variant="h5"
textTransform="capitalize"
+ style={{
+ whiteSpace: "nowrap",
+ textOverflow: "ellipsis",
+ overflow: "hidden",
+ maxWidth: "100%", // You can adjust this value as needed
+ }}
>
{title}
)}
-
-
+
+
{description}
diff --git a/src/examples/Navbars/DashboardNavbar/index.js b/src/examples/Navbars/DashboardNavbar/index.js
index d06adf9..e92ba06 100644
--- a/src/examples/Navbars/DashboardNavbar/index.js
+++ b/src/examples/Navbars/DashboardNavbar/index.js
@@ -153,7 +153,7 @@ function DashboardNavbar({ absolute, light, isMini }) {
{isMini ? null : (
navbarRow(theme, { isMini })}>
-
+
account_circle
diff --git a/src/firebase.js b/src/firebase.js
index 2cee295..41e0b2b 100644
--- a/src/firebase.js
+++ b/src/firebase.js
@@ -24,10 +24,21 @@ const firebaseConfig = {
measurementId: measurementId,
};
+// const firebaseConfig = {
+// apiKey: "AIzaSyAjKWWDuBXnKH40Ik3GX_4MIDUcjFGfjX4",
+// authDomain: "advizor-71682.firebaseapp.com",
+// projectId: "advizor-71682",
+// storageBucket: "advizor-71682.appspot.com",
+// messagingSenderId: "436861904344",
+// appId: "1:436861904344:web:52966dfa3937c3c9e9bead",
+// measurementId: "G-4MSLN0VTVP",
+// };
+
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const provider = new GoogleAuthProvider();
-export { auth, provider };
-export const storage = getStorage(app);
+const storage = getStorage(app);
+
+export { auth, provider, storage };
diff --git a/src/layouts/admin/contentapproval/contentApproval.js b/src/layouts/admin/contentapproval/contentApproval.js
index a17bbb5..e485b63 100644
--- a/src/layouts/admin/contentapproval/contentApproval.js
+++ b/src/layouts/admin/contentapproval/contentApproval.js
@@ -3,39 +3,48 @@ import Container from "@mui/material/Container";
import Typography from "@mui/material/Typography";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
-import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
import DashboardNavbar from "examples/Navbars/DashboardNavbar";
+import { fetchPendingAdvertisements } from "api/pendingAdvertisement/pendingAdvertisemnet";
+import MDButton from "components/MDButton";
// Simulated data for advertisements pending approval
-const advertisements = [
- {
- id: 1,
- title: "Historic Estate",
- location: "Jaffna",
- date: "Sun, 03 Sep 2023 18:30:04 GMT",
- description: "This is a historic estate.",
- image: "image_url_here",
- },
- {
- id: 2,
- title: "Historic Estate",
- location: "Jaffna",
- date: "Sun, 03 Sep 2023 18:30:04 GMT",
- description: "This is a historic estate.",
- image: "image_url_here",
- },
- // Add more advertisements as needed
-];
+// const advertisements = [
+// {
+// id: 1,
+// title: "Historic Estate",
+// location: "Jaffna",
+// date: "Sun, 03 Sep 2023 18:30:04 GMT",
+// description: "This is a historic estate.",
+// image: "image_url_here",
+// },
+// {
+// id: 2,
+// title: "Historic Estate",
+// location: "Jaffna",
+// date: "Sun, 03 Sep 2023 18:30:04 GMT",
+// description: "This is a historic estate.",
+// image: "image_url_here",
+// },
+// // Add more advertisements as needed
+// ];
function ContentApprovalPage() {
- const [pendingAds, setPendingAds] = useState(advertisements);
+ const [pendingAds, setPendingAds] = useState([]);
const [currentAdIndex, setCurrentAdIndex] = useState(0);
useEffect(() => {
- // Fetch pending advertisements from the server here if needed
- // Update the 'pendingAds' state with the fetched data
+ async function fetchData() {
+ try {
+ const data = await fetchPendingAdvertisements();
+ setPendingAds(data);
+ console.log(pendingAds);
+ } catch (error) {
+ console.error("Error fetching pending advertisements:", error);
+ }
+ }
+ fetchData();
}, []);
const approveAd = () => {
@@ -64,7 +73,7 @@ function ContentApprovalPage() {
}
};
- const currentAd = pendingAds[currentAdIndex];
+ //const currentAd = pendingAds[currentAdIndex];
return (
@@ -74,46 +83,59 @@ function ContentApprovalPage() {
Content Approval
- {currentAd ? (
-
-
-
- Advertisement ID: {currentAd.id}
-
-
- Title: {currentAd.title}
-
-
- Location: {currentAd.location}
-
-
- Date: {currentAd.date}
-
-
- Description: {currentAd.description}
-
- {currentAd.image && (
-
- )}
-
-
-
-
-
-
+ {pendingAds.length ? (
+ pendingAds.map((currentAd, index) => (
+
+
+
+ Advertisement ID: {currentAd.Advertisement_ID}
+
+
+ Category: {currentAd.Category}
+
+
+ Title: {currentAd.Title}
+
+
+ Location: {currentAd.Location.City}
+
+
+ Date: {currentAd.Posted_Date}
+
+
+ Description: {currentAd.Description}
+
+ {currentAd.image && (
+
+ )}
+
+
+ Approve
+
+
+ Edit
+
+
+ Reject
+
+
+
+
+ ))
) : (
No pending advertisements.
diff --git a/src/layouts/admin/managereports/data/managereportsdata.js b/src/layouts/admin/managereports/data/managereportsdata.js
new file mode 100644
index 0000000..af56ddb
--- /dev/null
+++ b/src/layouts/admin/managereports/data/managereportsdata.js
@@ -0,0 +1,135 @@
+/* eslint-disable react/prop-types */
+/* eslint-disable react/function-component-definition */
+/**
+ * =========================================================
+ * Material Dashboard 2 React - v2.2.0
+ * =========================================================
+ *
+ * Product Page: https://www.creative-tim.com/product/material-dashboard-react
+ * Copyright 2023 Creative Tim (https://www.creative-tim.com)
+ *
+ * Coded by www.creative-tim.com
+ *
+ * =========================================================
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+ */
+
+// Material Dashboard 2 React components
+import MDBox from "components/MDBox";
+import MDTypography from "components/MDTypography";
+import MDBadge from "components/MDBadge";
+import { useEffect, useState } from "react";
+import { getReportList } from "api/report/reportsdata";
+import { useUser } from "utils/userContext";
+
+export default function Data() {
+ const Job = ({ title, description }) => (
+
+
+ {title}
+
+ {description}
+
+ );
+
+ const [reportDetails, setReportsDetails] = useState([]);
+ const { user } = useUser();
+ const userID = user.user_ID;
+
+ useEffect(() => {
+ // Fetch average price data from the Flask API endpoint
+ getReportList(userID)
+ .then((data) => {
+ setReportsDetails(data);
+ console.log(data); // Use 'data' instead of 'reportDetails'
+ })
+ .catch((error) => {
+ console.error("Error fetching data:", error);
+ });
+ }, []);
+
+ const getFileExtension = (pdfUrl) => {
+ if (pdfUrl.toLowerCase().includes("pdf")) {
+ return "pdf";
+ } else if (pdfUrl.toLowerCase().includes("xlsx")) {
+ return "xlsx";
+ } else if (pdfUrl.toLowerCase().includes("csv")) {
+ return "csv";
+ } else {
+ return "pdf";
+ }
+ };
+ const mapExtensionToColor = (extension) => {
+ switch (extension) {
+ case "pdf":
+ return "error";
+ case "xlsx":
+ return "success"; // Change to the desired color for xls
+ case "csv":
+ return "warning"; // Change to the desired color for csv
+ default:
+ return "text"; // Replace with your default color
+ }
+ };
+
+ const handleDownload = (pdf_Url) => {
+ if (pdf_Url) {
+ // Create an anchor element to trigger the download
+ const anchor = document.createElement("a");
+ anchor.href = pdf_Url;
+ anchor.target = "_blank"; // Open the link in a new tab
+ anchor.download = "your_file_name.ext"; // Replace with the desired file name
+
+ // Trigger the download
+ anchor.click();
+ } else {
+ console.error("Download URL is not available.");
+ }
+ };
+
+ return {
+ columns: [
+ { Header: "Title", accessor: "author", align: "left" },
+ { Header: "Type", accessor: "function", align: "left" },
+ { Header: "Format", accessor: "status", align: "center" },
+ { Header: "Date", accessor: "employed", align: "center" },
+ { Header: "Download", accessor: "action", align: "center" },
+ ],
+ rows: reportDetails.map((report) => ({
+ author: (
+
+ {report.Title}
+
+ ),
+ function: ,
+ status: (
+
+
+
+ ),
+ employed: (
+
+ {report.timestamp}
+
+ ),
+ action: (
+ handleDownload(report.PDF_URL)} // Use an arrow function
+ >
+ Download
+
+ ),
+ })),
+ };
+}
diff --git a/src/layouts/admin/managereports/reportView.js b/src/layouts/admin/managereports/reportView.js
new file mode 100644
index 0000000..94bd4f8
--- /dev/null
+++ b/src/layouts/admin/managereports/reportView.js
@@ -0,0 +1,56 @@
+// export default ReportViewer;
+import React from "react";
+import Grid from "@mui/material/Grid";
+import Card from "@mui/material/Card";
+
+// Material Dashboard 2 React components
+import MDBox from "components/MDBox";
+import MDTypography from "components/MDTypography";
+
+import DataTable from "examples/Tables/DataTable";
+
+import data from "./data/managereportsdata";
+import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
+import DashboardNavbar from "examples/Navbars/DashboardNavbar";
+
+function ManageReports() {
+ const { columns, rows } = data();
+ return (
+
+
+
+
+
+
+
+
+ Reports History
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ManageReports;
diff --git a/src/layouts/admin/manageuser/data/userData.js b/src/layouts/admin/manageuser/data/userData.js
index 9b144ad..1e75abe 100644
--- a/src/layouts/admin/manageuser/data/userData.js
+++ b/src/layouts/admin/manageuser/data/userData.js
@@ -1,102 +1,102 @@
-/* eslint-disable react/prop-types */
-/* eslint-disable react/function-component-definition */
-/**
- * =========================================================
- * Material Dashboard 2 React - v2.2.0
- * =========================================================
- *
- * Product Page: https://www.creative-tim.com/product/material-dashboard-react
- * Copyright 2023 Creative Tim (https://www.creative-tim.com)
- *
- * Coded by www.creative-tim.com
- *
- * =========================================================
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- */
-
-// Material Dashboard 2 React components
import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
import MDBadge from "components/MDBadge";
import { useEffect, useState } from "react";
-import { getReportList } from "api/report/reportsdata";
+import { deleteUser, editUser, getUserList } from "api/ManageUser/users";
+import PropTypes from "prop-types";
export default function Data() {
- const Job = ({ title, description }) => (
+ const UserDetails = ({ name, email }) => (
- {title}
+ {name}
- {description}
+ {email}
);
- const [reportDetails, setReportsDetails] = useState([]);
+ UserDetails.propTypes = {
+ name: PropTypes.string.isRequired,
+ email: PropTypes.string.isRequired,
+ };
+ const [userDetails, setUserDetails] = useState([]);
useEffect(() => {
- // Fetch average price data from the Flask API endpoint
- getReportList()
+ getUserList()
.then((data) => {
- setReportsDetails(data);
- console.log(data); // Use 'data' instead of 'reportDetails'
+ setUserDetails(data);
+ console.log(data);
})
.catch((error) => {
- console.error("Error fetching data:", error);
+ console.error("Error fetching user data:", error);
});
}, []);
- const handleDownload = (pdf_Url) => {
- if (pdf_Url) {
- // Create an anchor element to trigger the download
- const anchor = document.createElement("a");
- anchor.href = pdf_Url;
- anchor.target = "_blank"; // Open the link in a new tab
- anchor.download = "your_file_name.ext"; // Replace with the desired file name
+ const handleUserDelete = (userId) => {
+ if (userId) {
+ // Add code to delete the user using the user ID
+ deleteUser(userId);
+ } else {
+ console.error("User ID is not available.");
+ }
+ };
- // Trigger the download
- anchor.click();
+ const handleUserEdit = (userId) => {
+ if (userId) {
+ // Add code to edit the user using the user ID
+ editUser(userId);
} else {
- console.error("Download URL is not available.");
+ console.error("User ID is not available.");
}
};
return {
columns: [
- { Header: "User", accessor: "author", align: "left" },
- { Header: "Profession", accessor: "function", align: "left" },
- { Header: "Status", accessor: "status", align: "center" },
- { Header: "Last Seen", accessor: "employed", align: "center" },
+ { Header: "Name", accessor: "name", align: "left" },
+ { Header: "Email", accessor: "email", align: "left" },
+ { Header: "Role", accessor: "role", align: "center" },
+ { Header: "Last Seen", accessor: "lastSeen", align: "center" },
{ Header: "Manage", accessor: "action", align: "center" },
],
- rows: reportDetails.map((report) => ({
- author: (
+ rows: userDetails.map((user) => ({
+ name: (
- {report.Title}
+ {user.Full_Name}
),
- function: ,
- status: (
-
-
-
+ email: ,
+ role: (
+
+ {user.Profession}
+
),
- employed: (
+ lastSeen: (
- {report.timestamp}
+ {user.Last_Seen}
),
action: (
- handleDownload(report.PDF_URL)} // Use an arrow function
- >
- Download
-
+
+ handleUserDelete(user._id)} // Use an arrow function
+ />
+ handleUserEdit(user._id)} // Use an arrow function
+ />
+
),
})),
};
diff --git a/src/layouts/admin/submitadvertisement/submitad.js b/src/layouts/admin/submitadvertisement/submitad.js
index a1ad889..dbfed9d 100644
--- a/src/layouts/admin/submitadvertisement/submitad.js
+++ b/src/layouts/admin/submitadvertisement/submitad.js
@@ -151,7 +151,7 @@
// export default AdvertisementForm;
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import Container from "@mui/material/Container";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
@@ -160,29 +160,49 @@ import Box from "@mui/material/Box";
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
import DashboardNavbar from "examples/Navbars/DashboardNavbar";
-import { Card } from "@mui/material";
+import { Card, Menu, MenuItem } from "@mui/material";
import MDButton from "components/MDButton";
+import MDBox from "components/MDBox";
+import MDInput from "components/MDInput";
+import { submitAdvertisement } from "api/submitAdvertisement/submitAdvertisement";
+import { storage } from "../../../firebase";
+import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
+import { v4 } from "uuid";
function AdvertisementForm() {
const [formData, setFormData] = useState({
title: "",
location: "",
- date: "",
description: "",
image: null,
category: "", // New category field
});
+ const initialFormData = {
+ title: "",
+ location: "",
+ description: "",
+ image: null,
+ category: "",
+ };
const [imagePreview, setImagePreview] = useState(null);
const handleChange = (e) => {
const { name, value } = e.target;
- setFormData({ ...formData, [name]: value });
+ if (name === "phoneNumbers" || name == "landMarks") {
+ const phoneNumbers = value.split(",").map((number) => number.trim());
+ setFormData({ ...formData, [name]: phoneNumbers });
+ } else {
+ setFormData({ ...formData, [name]: value });
+ }
};
- const handleImageChange = (e) => {
+ const handleImageChange = async (e) => {
const file = e.target.files[0];
- setFormData({ ...formData, image: file });
+ const imageRef = ref(storage, `advertisement-picture/${v4()}`); // Define the reference to the image
+ await uploadBytes(imageRef, file); // Upload the image bytes
+ const url = await getDownloadURL(imageRef);
+ setFormData({ ...formData, image: url });
const reader = new FileReader();
reader.onload = (event) => {
@@ -191,19 +211,70 @@ function AdvertisementForm() {
reader.readAsDataURL(file);
};
- const handleSubmit = (e) => {
+ // const [position, setPosition] = useState([]);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ // Split the locationsParam into individual city names
+ const cityName = formData.nearestCity;
+ // Initialize an array to store marker locations
+ const markerLocations = [];
+ // Use a geocoding service (like OpenStreetMap Nominatim) to get coordinates for each city
+ const response = await fetch(
+ `https://nominatim.openstreetmap.org/search?format=json&q=${cityName}`
+ );
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+ const data = await response.json();
+ // Check if the response contains valid data
+ if (Array.isArray(data) && data.length > 0) {
+ const location = data[0]; // Take the first result
+ // const position = [parseFloat(location.lat), parseFloat(location.lon)];
+ // setPosition([parseFloat(location.lat), parseFloat(location.lon)]);
+ formData.longitude = parseFloat(location.lon);
+ formData.lattitude = parseFloat(location.lat);
+ markerLocations.push({
+ name: cityName,
+ Location: {
+ Latitude: parseFloat(location.lat),
+ Longitude: parseFloat(location.lon),
+ },
+ });
+ }
+
+ // Update the markers state with the retrieved locations
+ } catch (error) {
+ console.error("Error fetching marker data:", error);
+ }
+ };
+ fetchData();
+ }, [formData.nearestCity, formData.longitude, formData.lattitude]);
+
+ const handleSubmit = async (e) => {
e.preventDefault();
- console.log("Form data:", formData);
+ if (formData.category) {
+ try {
+ const response = await submitAdvertisement(formData);
+ console.log("Advertisement submitted successfully:", response);
+ setFormData(initialFormData);
+ } catch (error) {
+ console.error("Error submitting advertisement:", error);
+ }
+ } else {
+ alert("Select a category");
+ }
};
// Define form fields based on category
let categoryFields;
- if (formData.category === "landsale") {
+ if (formData.category === "Land Sale") {
categoryFields = (
<>
- Price per Perch
+ Price per Perch in LKR
@@ -218,11 +290,11 @@ function AdvertisementForm() {
Number of Perches
@@ -230,12 +302,12 @@ function AdvertisementForm() {
Posted on
@@ -284,6 +356,31 @@ function AdvertisementForm() {
name="nearestCity"
value={formData.nearestCity}
onChange={handleChange}
+ required
+ />
+
+
+
+ Longitude
+
+
+
+
+
+ Lattitude
+
+
@@ -312,12 +409,12 @@ function AdvertisementForm() {
>
);
- } else if (formData.category === "housesale") {
+ } else if (formData.category === "House Sale") {
categoryFields = (
<>
- Price
+ Price in LKR
@@ -332,11 +430,11 @@ function AdvertisementForm() {
Number of rooms
@@ -344,12 +442,12 @@ function AdvertisementForm() {
Posted on
@@ -398,6 +496,31 @@ function AdvertisementForm() {
name="nearestCity"
value={formData.nearestCity}
onChange={handleChange}
+ required
+ />
+
+
+
+ Longitude
+
+
+
+
+
+ Lattitude
+
+
@@ -415,7 +538,7 @@ function AdvertisementForm() {
{/* Add more fields for housesale */}
>
);
- } else if (formData.category === "marriageproposals") {
+ } else if (formData.category === "Marriage Proposals") {
categoryFields = (
<>
@@ -423,23 +546,33 @@ function AdvertisementForm() {
Gender
+ select
+ SelectProps={{
+ // Add this prop to style the Select component
+ style: { minHeight: "40px", minWidth: "100px" }, // You can adjust the height as needed
+ }}
+ >
+
+
+
+
Age
@@ -477,6 +610,7 @@ function AdvertisementForm() {
value={formData.requirements}
onChange={handleChange}
style={{ width: "100%" }}
+ required
/>
@@ -484,12 +618,12 @@ function AdvertisementForm() {
Posted on
@@ -538,6 +672,31 @@ function AdvertisementForm() {
name="nearestCity"
value={formData.nearestCity}
onChange={handleChange}
+ required
+ />
+
+
+
+ Longitude
+
+
+
+
+
+ Lattitude
+
+
@@ -557,27 +716,82 @@ function AdvertisementForm() {
);
}
+ // const handleChangeMenu = (event) => {};
+
+ const [categoryMenu, setCategoryMenu] = useState(null);
+
+ const openCategoryMenu = ({ currentTarget }) => setCategoryMenu(currentTarget);
+ const closeCategoryMenu = () => setCategoryMenu(null);
+ const [category, setCategory] = useState("");
+
+ const handleCategoryMenuItemClick = (dataKey) => {
+ setCategory(dataKey);
+ formData.category = dataKey;
+ closeCategoryMenu();
+ };
+
+ const renderCategoryMenu = (
+
+ );
return (
-
-
+
+
Submit Advertisement
- {adDetails.source}
+ {adDetails.Source}
@@ -562,7 +562,7 @@ const Addetail = () => {
- {adDetails.source}
+ {adDetails.Source}
diff --git a/src/layouts/authentication/components/Footer/index.js b/src/layouts/authentication/components/Footer/index.js
index 812de4a..69473fd 100644
--- a/src/layouts/authentication/components/Footer/index.js
+++ b/src/layouts/authentication/components/Footer/index.js
@@ -57,7 +57,7 @@ function Footer({ light }) {
by
-
+
Advizor
diff --git a/src/layouts/authentication/reset-password/cover/index.js b/src/layouts/authentication/reset-password/cover/index.js
index 67b17cf..6fb317b 100644
--- a/src/layouts/authentication/reset-password/cover/index.js
+++ b/src/layouts/authentication/reset-password/cover/index.js
@@ -1,36 +1,57 @@
-/**
-=========================================================
-* Material Dashboard 2 React - v2.2.0
-=========================================================
-
-* Product Page: https://www.creative-tim.com/product/material-dashboard-react
-* Copyright 2023 Creative Tim (https://www.creative-tim.com)
-
-Coded by www.creative-tim.com
-
- =========================================================
-
-* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-*/
-
-// @mui material components
+import React, { useState } from "react";
import Card from "@mui/material/Card";
-
-// Material Dashboard 2 React components
import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
import MDInput from "components/MDInput";
import MDButton from "components/MDButton";
-
-// Authentication layout components
import CoverLayout from "layouts/authentication/components/CoverLayout";
+import bgImage from "assets/images/newsback.jpg";
+import baseURL from "config";
+import { useNavigate } from "react-router-dom";
+import MDAlert from "components/MDAlert";
+import VerificationDialog from "layouts/authentication/sign-up/VerificationDialog";
+
+function ResetPSW() {
+ const [email, setEmail] = useState("");
+ const [verificationOpen, setVerificationOpen] = useState(false);
+ const [showSuccessAlert, setShowSuccessAlert] = useState(false);
+ const navigate = useNavigate();
+
+ const handleSend = () => {
+ console.log(email);
+ if (email === "") {
+ alert("Please enter email");
+ return;
+ }
+
+ // Send the email to the backend
+ fetch(`${baseURL}/reset-password`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ email }),
+ })
+ .then((response) => {
+ response.json();
+ })
-// Images
-import bgImage from "assets/images/bg-reset-cover.jpeg";
+ .then((data) => {
+ console.log("this is verification", data);
+ setVerificationOpen(true);
+ })
+ .catch((error) => {
+ console.error("Error:", error);
+ });
+ };
-function Cover() {
return (
+ {showSuccessAlert && (
+
+ entered code is correct
+
+ )}
- You will receive an e-mail in maximum 60 seconds
+ You will receive a temporary password
-
+ setEmail(e.target.value)}
+ />
-
- reset
+
+ SEND CODE
+ {verificationOpen && (
+ setVerificationOpen(false)}
+ email={email} // Pass the email to the dialog
+ onSuccess={() => {
+ // Handle successful verification if needed
+ setShowSuccessAlert(true);
+ setTimeout(() => {
+ setShowSuccessAlert(false);
+ navigate(`/authentication/sign-in`);
+ }, 1000);
+ }}
+ address={"verify-email"}
+ />
+ )}
);
}
-export default Cover;
+export default ResetPSW;
diff --git a/src/layouts/authentication/reset-password/cover/newpassword.js b/src/layouts/authentication/reset-password/cover/newpassword.js
new file mode 100644
index 0000000..a53ebca
--- /dev/null
+++ b/src/layouts/authentication/reset-password/cover/newpassword.js
@@ -0,0 +1,58 @@
+import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
+
+import baseURL from "config";
+import React, { useState } from "react";
+
+function NewPassword() {
+ const [password, setPassword] = useState("");
+
+ const handleSubmit = (event) => {
+ event.preventDefault();
+ if (password === "") {
+ alert("Please enter password");
+ return;
+ }
+
+ // Send the password to the backend
+ fetch(`${baseURL}/new-password`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ password }),
+ })
+ .then((response) => {
+ response.json();
+ })
+
+ .then((data) => {
+ console.log("this is verification", data);
+ })
+ .catch((error) => {
+ console.error("Error:", error);
+ });
+ // TODO: handle password submission
+ };
+
+ return (
+
+
+ Reset Password
+
+
+
+ );
+}
+
+export default NewPassword;
diff --git a/src/layouts/authentication/sign-in/index.js b/src/layouts/authentication/sign-in/index.js
index 157669d..1e3dee7 100644
--- a/src/layouts/authentication/sign-in/index.js
+++ b/src/layouts/authentication/sign-in/index.js
@@ -1,18 +1,3 @@
-/**
-=========================================================
-* Material Dashboard 2 React - v2.2.0
-=========================================================
-
-* Product Page: https://www.creative-tim.com/product/material-dashboard-react
-* Copyright 2023 Creative Tim (https://www.creative-tim.com)
-
-Coded by www.creative-tim.com
-
- =========================================================
-
-* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-*/
-
import { useState } from "react";
// react-router-dom components
@@ -20,7 +5,7 @@ import { Link } from "react-router-dom";
// @mui material components
import Card from "@mui/material/Card";
-import Switch from "@mui/material/Switch";
+// import Switch from "@mui/material/Switch";
// Material Dashboard 2 React components
import MDBox from "components/MDBox";
@@ -46,13 +31,16 @@ function Basic() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
- const [rememberMe, setRememberMe] = useState(false);
+ // const [rememberMe, setRememberMe] = useState(false);
- const handleSetRememberMe = () => setRememberMe(!rememberMe);
- const handleForgetPassword = () => {};
+ // const handleSetRememberMe = () => setRememberMe(!rememberMe);
const [value, setValue] = useState("");
const navigate = useNavigate();
+ const handleForgetPassword = () => {
+ navigate("/authentication/reset-password");
+ };
+
const handleClick = () => {
signInWithPopup(auth, provider).then((data) => {
setValue(data.user.email);
@@ -61,44 +49,6 @@ function Basic() {
});
};
- // const handleLogin = () => {
- // if (!email || !password) {
- // alert("Please enter both email and password");
- // return;
- // }
- // fetch("/login", {
- // method: "POST",
- // headers: {
- // "Content-Type": "application/json",
- // },
- // body: JSON.stringify({
- // email: email,
- // password: password,
- // }),
- // })
- // .then((response) => {
- // if (!response.ok) {
- // throw response.status;
- // }
- // return response.json();
- // })
- // .then((data) => {
- // console.log(data);
- // // Display a success message if applicable
- // login({ name: email, role: "user" });
- // navigate("/dashboard");
- // })
- // .catch((status) => {
- // console.log(status, "error");
- // if (status === 400) {
- // alert("Email and password are required.");
- // } else if (status === 401) {
- // alert("Invalid User Name or Incorrect Password.");
- // } else {
- // alert("An error occurred during login.");
- // }
- // });
- // };
const handleLogin = () => {
if (!email || !password) {
alert("Please enter both email and password");
@@ -124,7 +74,6 @@ function Basic() {
if (data && data.user) {
// Display a success message if applicable
const userData = data.user;
- console.log(userData);
login({
name: userData.User_Name,
full_name: userData.Full_Name,
@@ -133,23 +82,24 @@ function Basic() {
email: userData.email,
phone_Number: userData.Contact_Number,
profession: userData.Profession,
+ Profile_Picture: userData.Profile_Picture,
+ Last_Seen: userData.Last_Seen,
});
- // Now you can use userData as needed in your frontend
- // For example, you can store it in state or context for later use
- // login({ name: userData.User_Name, role: "user" });
+ // if (rememberMe) {
+ // Cookies.set("user_id", userData.UserID, { expires: 365 }); // The cookie expires in 365 days
+ // }
navigate("/dashboard");
} else {
alert("User data not found in the response.");
}
})
.catch((status) => {
- console.log(status, "error");
if (status === 400) {
alert("Email and password are required.");
} else if (status === 401) {
alert("Invalid User Name or Incorrect Password.");
} else {
- alert("An error occurred during login.");
+ alert("Check your Network Connection");
}
});
};
@@ -157,38 +107,6 @@ function Basic() {
return (
- {/*
-
- Sign in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- */}
-
+ {/*
Remember me
-
+ */}
-
-
- Use "test@advizor.com" and "test" as demo-credentials
-
-
Log in
diff --git a/src/layouts/authentication/sign-up/VerificationDialog.js b/src/layouts/authentication/sign-up/VerificationDialog.js
index fa1219a..5754784 100644
--- a/src/layouts/authentication/sign-up/VerificationDialog.js
+++ b/src/layouts/authentication/sign-up/VerificationDialog.js
@@ -9,11 +9,16 @@ import DialogTitle from "@mui/material/DialogTitle";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
import baseURL from "config";
+import { useUser } from "utils/userContext";
-export default function VerificationDialog({ open, onClose, email, onSuccess }) {
+export default function VerificationDialog({ open, onClose, email, onSuccess, address }) {
const [verificationCode, setVerificationCode] = useState("");
const [timeRemaining, setTimeRemaining] = useState(60);
const [alertType, setAlertType] = useState(null);
+ const [alertPassword, setAlertPassword] = useState(false);
+ const [hideComponent, sethideComponent] = useState(true);
+ const [newpassword, setNewPassword] = useState("");
+ const { login } = useUser();
useEffect(() => {
let interval = null;
@@ -23,12 +28,10 @@ export default function VerificationDialog({ open, onClose, email, onSuccess })
setTimeRemaining((prevTime) => prevTime - 1);
}, 1000);
- // Clear interval when component unmounts or dialog closes
return () => {
clearInterval(interval);
};
} else if (!open) {
- // Reset timer when dialog closes
setTimeRemaining(60);
}
}, [open, timeRemaining]);
@@ -36,22 +39,39 @@ export default function VerificationDialog({ open, onClose, email, onSuccess })
const handleVerificationSubmit = () => {
if (verificationCode) {
axios
- .post(`${baseURL}/verify`, {
+ .post(`${baseURL}/${address}`, {
email: email,
verificationCode: verificationCode,
})
.then(function (response) {
console.log(response);
if (response.data.success) {
- // alert("Registration successful!");
setAlertType("success");
console.log(alertType);
- onSuccess();
- } else {
- setAlertType("error");
- alert("Verification code is incorrect or expired.");
+ if (address === "verify") {
+ const userData = response.data.user;
+ login({
+ name: userData.User_Name,
+ full_name: userData.Full_Name,
+ user_ID: userData.UserID,
+ role: userData.Role,
+ email: userData.email,
+ phone_Number: userData.Contact_Number,
+ profession: userData.Profession,
+ Profile_Picture: userData.Profile_Picture,
+ });
+ onSuccess();
+ onClose();
+ } else if (address === "verify-email") {
+ setAlertPassword(true);
+ sethideComponent(false);
+ setNewPassword(response.data.newpassword);
+ // onSuccess();
+ } else {
+ setAlertType("error");
+ alert("Verification code is incorrect or expired.");
+ }
}
- onClose();
})
.catch(function (error) {
console.log(error, "error");
@@ -59,16 +79,20 @@ export default function VerificationDialog({ open, onClose, email, onSuccess })
}
};
+ const handlePasswordSubmit = () => {
+ onSuccess();
+ onClose();
+ };
+
const handleCancel = () => {
axios
.post(`${baseURL}/verify`, {
email: email,
- verificationCode: "", // Provide an empty code to indicate cancellation
- cancel: true, // Add a flag to indicate cancellation
+ verificationCode: "",
+ cancel: true,
})
.then(function (response) {
console.log(response);
- // setVerificationOpen(false);
onClose();
})
.catch(function (error) {
@@ -77,46 +101,64 @@ export default function VerificationDialog({ open, onClose, email, onSuccess })
};
return (
-
+ {alertPassword && (
+ <>
+ Verification Successful
+
+
+ Your new password is {newpassword} Important: Please imediately change your password
+ after login
+
+
+
+
+
+ >
+ )}
+
+ >
);
}
diff --git a/src/layouts/authentication/sign-up/index.js b/src/layouts/authentication/sign-up/index.js
index 989f6c7..e030aff 100644
--- a/src/layouts/authentication/sign-up/index.js
+++ b/src/layouts/authentication/sign-up/index.js
@@ -23,7 +23,6 @@ import bgImage from "assets/images/newspaper2.jpg";
import VerificationDialog from "./VerificationDialog";
import { useNavigate } from "react-router-dom";
-import { useUser } from "utils/userContext";
import baseURL from "config";
import TermModal from "./term";
@@ -33,7 +32,6 @@ function Cover() {
const [name, setName] = useState("");
const navigate = useNavigate();
const [showSuccessAlert, setShowSuccessAlert] = useState(false);
- const { login } = useUser();
const [verificationOpen, setVerificationOpen] = useState(false);
@@ -94,22 +92,7 @@ function Cover() {
} else {
return response.json().then((data) => {
console.log(data);
- // Handle success, e.g., show a success message to the user
- // alert(data.message);
- const userData = data.user;
- console.log(userData);
- login({
- name: userData.User_Name,
- full_name: userData.Full_Name,
- user_ID: userData.UserID,
- role: userData.Role,
- email: userData.email,
- phone_Number: userData.Contact_Number,
- profession: userData.Profession,
- });
setVerificationOpen(true);
-
- // navigate("/dashboard");
});
}
})
@@ -200,8 +183,6 @@ function Cover() {
I agree the
setVerificationOpen(false)}
- email={email} // Pass the email to the dialog
+ email={email}
onSuccess={() => {
- // Handle successful verification if needed
setShowSuccessAlert(true);
setTimeout(() => {
setShowSuccessAlert(false);
navigate("/dashboard");
}, 1000);
}}
+ address={"verify"}
/>
)}
diff --git a/src/layouts/authentication/sign-up/term.js b/src/layouts/authentication/sign-up/term.js
index 09ece52..8e19660 100644
--- a/src/layouts/authentication/sign-up/term.js
+++ b/src/layouts/authentication/sign-up/term.js
@@ -9,10 +9,9 @@ import MDTypography from "components/MDTypography";
function TermModal({ open, onClose }) {
const cardContentStyle = {
- // Add your desired width and height for the modal
- width: "80%", // Adjust as needed
- height: "80vh", // Adjust as needed
- overflowY: "scroll", // Add a vertical scroll when the content exceeds the height
+ width: "80%",
+ height: "80vh",
+ overflowY: "scroll",
};
return (
({
@@ -63,11 +62,7 @@ export default function data() {
date: ad.Posted_Date,
address: ad.Location.Address, // Use the correct field for the address
phoneNumber: ad.Contact_Info.Phone_Number.join(", "), // Join multiple phone numbers if available
- price: (
-
- Rs.{ad.Price_per_Perch}
-
- ),
+ price: ad.Price_per_Perch,
})),
},
@@ -81,7 +76,7 @@ export default function data() {
{ Header: "Posted Date", accessor: "date", align: "center" },
//{ Header: "Address", accessor: "address", align: "center" },
{ Header: "PhoneNumber", accessor: "phoneNumber", align: "center" },
- { Header: "Price", accessor: "price", align: "center" },
+ { Header: "Price in Rs.", accessor: "price", align: "center" },
],
rows: recentHouseAds.map((ad, index) => ({
@@ -93,11 +88,7 @@ export default function data() {
address: ad.Location.Address, // Use the correct field for the address
phoneNumber: ad.Contact_Info.Phone_Number.join(", "), // Join multiple phone numbers if available
No_of_Rooms: ad.Number_of_Rooms,
- price: (
-
- Rs.{ad.Price}
-
- ),
+ price: ad.Price,
})),
},
diff --git a/src/layouts/dashboard/components/Projects/index.js b/src/layouts/dashboard/components/Projects/index.js
index c79e7df..e6938e1 100644
--- a/src/layouts/dashboard/components/Projects/index.js
+++ b/src/layouts/dashboard/components/Projects/index.js
@@ -1,19 +1,4 @@
-/**
-=========================================================
-* Material Dashboard 2 React - v2.2.0
-=========================================================
-
-* Product Page: https://www.creative-tim.com/product/material-dashboard-react
-* Copyright 2023 Creative Tim (https://www.creative-tim.com)
-
-Coded by www.creative-tim.com
-
- =========================================================
-
-* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-*/
-
-import { useState } from "react";
+import { useEffect, useState } from "react";
// @mui material components
import Card from "@mui/material/Card";
@@ -34,10 +19,12 @@ import data from "layouts/dashboard/components/Projects/data";
function Projects() {
const { landSale, houseSale, marriageProposals } = data();
const [menu, setMenu] = useState(null);
- const [selectedData, setSelectedData] = useState(landSale);
-
+ const [selectedData, setSelectedData] = useState(() => landSale);
const openMenu = ({ currentTarget }) => setMenu(currentTarget);
const closeMenu = () => setMenu(null);
+ useEffect(() => {
+ setSelectedData(landSale);
+ }, []);
const handleMenuItemClick = (dataKey) => {
setSelectedData(dataKey);
closeMenu();
diff --git a/src/layouts/dashboard/components/SearchBar/searchBar.js b/src/layouts/dashboard/components/SearchBar/searchBar.js
index a46b8d8..be29e22 100644
--- a/src/layouts/dashboard/components/SearchBar/searchBar.js
+++ b/src/layouts/dashboard/components/SearchBar/searchBar.js
@@ -12,7 +12,7 @@ import { Grid, Pagination, useMediaQuery } from "@mui/material";
import { getAdbyFilter } from "api/searchBar/getAdbyFilter";
import MDTypography from "components/MDTypography";
import { Link } from "react-router-dom";
-import Loading from "components/Loading";
+import Loading from "react-loading";
// import MDPagination from "components/MDPagination";
const AdvertisementSearch = () => {
@@ -48,12 +48,14 @@ const AdvertisementSearch = () => {
const [selectedData, setSelectedData] = useState([]);
const [currentPage, setCurrentPage] = useState(0);
+ const [noresult, setNoresult] = useState(false);
const adsPerPage = 20;
const handleSearch = async () => {
try {
// Implement your search logic here, fetching data based on the selected option and query
// For example, you can use the getRecentAd function from the API file
+ setNoresult(false);
setCurrentPage(0);
setLoading(true);
const searchData = await getAdbyFilter(
@@ -64,6 +66,9 @@ const AdvertisementSearch = () => {
category
);
setSelectedData(searchData);
+ if (searchData.length === 0) {
+ setNoresult(true);
+ }
setLoading(false);
} catch (error) {
console.error("Error searching:", error);
@@ -146,28 +151,6 @@ const AdvertisementSearch = () => {
// Get ads for the current page
const currentAds = selectedData.slice(startIndex, endIndex);
- // const advertisementData = {
- // columns: [
- // { Header: "#", accessor: "index", width: "5%", align: "left" },
- // { Header: "Title", accessor: "title", width: "10%", align: "left" },
- // { Header: "Source", accessor: "source", align: "center" },
- // { Header: "Location", accessor: "city", align: "center" },
- // { Header: "Posted Date", accessor: "date", align: "center" },
- // //{ Header: "Address", accessor: "address", align: "center" },
- // { Header: "PhoneNumber", accessor: "phoneNumber", align: "center" },
- // { Header: "Description", accessor: "description", align: "center" },
- // ],
- // rows: selectedData.map((ad, index) => ({
- // index: index + 1,
- // title: ad.Title,
- // source: ad.Source, // You can choose an appropriate field for the source
- // city: ad.Location.City,
- // date: ad.Posted_Date,
- // phoneNumber: ad.Contact_Info.Phone_Number.join(", "), // Join multiple phone numbers if available
- // description: ad.Description,
- // })), // Add your data here
- // };
- // Customized page options starting from 1
const isMobile = useMediaQuery("(max-width: 600px)");
return (
@@ -267,57 +250,29 @@ const AdvertisementSearch = () => {
-
-
- {loading && }
-
- {" "}
- {/* Use Grid container */}
- {currentAds.map((ad, index) => (
-
- {" "}
- {/* Use Grid item */}
-
-
- ))}
-
- {selectedData.length > adsPerPage && (
- //
- //
- //
- // keyboard_arrow_left
- //
- //
- // 1
- //
- // 2
- // 3
- //
- // keyboard_arrow_right
- //
- //
-
-
- handlePageChange(page)}
- />
-
-
- )}
-
+
+ {loading && }
+ {noresult && No Search results found}
+
+ {currentAds.map((ad, index) => (
+
+
+
+ ))}
+
+ {selectedData.length > adsPerPage && (
+
+
+ handlePageChange(page)}
+ />
+
+
+ )}
+
);
};
diff --git a/src/layouts/dashboard/components/SearchBar/searchResultCard.js b/src/layouts/dashboard/components/SearchBar/searchResultCard.js
index 5c2a0f1..ce230fd 100644
--- a/src/layouts/dashboard/components/SearchBar/searchResultCard.js
+++ b/src/layouts/dashboard/components/SearchBar/searchResultCard.js
@@ -7,6 +7,7 @@ import homeDecor2 from "assets/images/house (1).jpg";
import homeDecor3 from "assets/images/wedding.jpg";
const SearchResultCard = ({ ad }) => {
+ const { Image } = ad;
// Extract the category from the Advertisement_ID
const getCategoryFromId = (advertisementId) => {
const idNumber = parseInt(advertisementId[2]);
@@ -33,7 +34,7 @@ const SearchResultCard = ({ ad }) => {
return (
{
{
color: "info",
label: "view Ad",
}}
- // authors={123}
/>
diff --git a/src/layouts/feedback/feedback.js b/src/layouts/feedback/feedback.js
index 76d01af..e4ba577 100644
--- a/src/layouts/feedback/feedback.js
+++ b/src/layouts/feedback/feedback.js
@@ -3,14 +3,26 @@ import { Card, Checkbox, TextField } from "@mui/material";
import MDBox from "components/MDBox";
import MDButton from "components/MDButton";
import MDTypography from "components/MDTypography";
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import { submitFeedback } from "api/feedback/saveFeedback";
import { useUser } from "utils/userContext";
+import { getFeedbackData } from "api/feedback/getFeedback";
+import Loading from "components/Loading";
+
+// Helper function to render the rating as stars
+const renderRatingStars = (rating) => {
+ const starArray = [];
+ for (let i = 0; i < rating; i++) {
+ starArray.push(★); // Render a star character
+ }
+ return starArray;
+};
const FeedbackSection = () => {
const [rating, setRating] = useState(0);
const [feedback, setFeedback] = useState("");
const [publish, setPublish] = useState(false);
+ const [loading, setLoading] = useState(false);
const { user } = useUser();
const userID = user.user_ID;
@@ -36,60 +48,104 @@ const FeedbackSection = () => {
}
};
+ const [feedbackData, setFeedbackData] = useState([]);
+
+ useEffect(() => {
+ // Fetch feedback data when the component mounts
+ async function fetchFeedbackData() {
+ try {
+ setLoading(true);
+ const data = await getFeedbackData();
+ setFeedbackData(data);
+ setLoading(false);
+ } catch (error) {
+ console.error("Error fetching feedback data:", error);
+ }
+ }
+ fetchFeedbackData();
+ }, []);
+
return (
-
-
-
-
- Rate our Newspaper Advertisement Analyzer
-
-
- {[1, 2, 3, 4, 5].map((star) => (
- handleRatingChange(star)}
- style={{
- cursor: "pointer",
- color: star <= rating ? "orange" : "gray",
- fontSize: "50px",
- }}
- >
- ★
-
- ))}
+
+
+
+
+
+ Rate our Newspaper Advertisement Analyzer
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+ handleRatingChange(star)}
+ style={{
+ cursor: "pointer",
+ color: star <= rating ? "orange" : "gray",
+ fontSize: "50px",
+ }}
+ >
+ ★
+
+ ))}
+
+
+
+ Your Comment is extremely valuable to us
+
+
+
+
+
+
+
+
+ Submit Feedback
+
-
-
- Your Comment is extremely valuable to us
-
-
-
-
-
-
-
-
- Submit Feedback
-
-
-
+
+
+
{loading && }
+ {feedbackData.map((feedback, index) => (
+
+
+
+ {feedback.user_name || feedback.Full_Name || "Anonymous"}
+
+
+ {feedback.email}
+
+
+ {feedback.rating && renderRatingStars(feedback.rating)} |{" "}
+ {feedback.date && new Date(feedback.date).toDateString()}
+
+
+ {feedback.feedback}
+
+
+ {new Date(feedback.timestamp.$date).toLocaleString() || feedback.timestamp.$date}
+
+ {/* You can add buttons or actions here for managing feedback */}
+
+
+ ))}
+
);
};
diff --git a/src/layouts/landing/App.js b/src/layouts/landing/App.js
index 61747ea..8920c9c 100644
--- a/src/layouts/landing/App.js
+++ b/src/layouts/landing/App.js
@@ -9,7 +9,7 @@ import Action from "./Page/Action";
import "./index.css";
// import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
// import DashboardNavbar from "examples/Navbars/DashboardNavbar";
-// import backgroundImage from "./Assets/images/background8.jpg";
+import backgroundImage from "./Assets/images/background11.png";
import DefaultNavbar from "examples/Navbars/DefaultNavbar";
import Configurator from "examples/Configurator";
import { useMaterialUIController, setOpenConfigurator } from "context";
@@ -18,7 +18,7 @@ import MDBox from "components/MDBox";
function App() {
const containerStyle = {
- // backgroundImage: `url(${backgroundImage})`,
+ backgroundImage: `url(${backgroundImage})`,
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
};
diff --git a/src/layouts/landing/Assets/images/background11.png b/src/layouts/landing/Assets/images/background11.png
new file mode 100644
index 0000000..9731a9f
Binary files /dev/null and b/src/layouts/landing/Assets/images/background11.png differ
diff --git a/src/layouts/profile/components/Header/index.js b/src/layouts/profile/components/Header/index.js
index 1c93135..e79bc0e 100644
--- a/src/layouts/profile/components/Header/index.js
+++ b/src/layouts/profile/components/Header/index.js
@@ -35,17 +35,20 @@ import MDAvatar from "components/MDAvatar";
import breakpoints from "assets/theme/base/breakpoints";
// Images
-import burceMars from "assets/images/socrates.jpeg";
+//import burceMars from "assets/images/socrates.jpeg";
import backgroundImage from "assets/images/bg-profile.jpeg";
import { useUser } from "utils/userContext";
+import ProfileModal from "./updateprofile";
function Header({ children }) {
const [tabsOrientation, setTabsOrientation] = useState("horizontal");
const [tabValue, setTabValue] = useState(0);
const { user } = useUser();
+ const [image, setImage] = useState(user.Profile_Picture);
useEffect(() => {
// A function that sets the orientation state of the tabs.
+ console.log(image);
function handleTabsOrientation() {
return window.innerWidth < breakpoints.values.sm
? setTabsOrientation("vertical")
@@ -66,6 +69,16 @@ function Header({ children }) {
const handleSetTabValue = (event, newValue) => setTabValue(newValue);
+ const [isModalOpen, setIsModalOpen] = useState(false);
+
+ const handleOpenModal = () => {
+ setIsModalOpen(true);
+ };
+
+ const handleCloseModal = () => {
+ setIsModalOpen(false);
+ };
+
return (
-
+
+
{/* */}
diff --git a/src/layouts/profile/components/Header/updateprofile.js b/src/layouts/profile/components/Header/updateprofile.js
new file mode 100644
index 0000000..eb64fd6
--- /dev/null
+++ b/src/layouts/profile/components/Header/updateprofile.js
@@ -0,0 +1,125 @@
+import React, { useState } from "react";
+import PropTypes from "prop-types";
+import Modal from "@mui/material/Modal";
+import Card from "@mui/material/Card";
+import CardContent from "@mui/material/CardContent";
+import Grid from "@mui/material/Grid";
+import MDTypography from "components/MDTypography";
+import MDButton from "components/MDButton";
+import MDBox from "components/MDBox";
+import { storage } from "../../../../firebase";
+import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
+import { useUser } from "utils/userContext";
+import { updateProfilePicture } from "api/updateUser/updateUser";
+import ReactLoading from "react-loading";
+
+function ProfileModal({ open, onClose, image, setImage }) {
+ const [selectedImage, setSelectedImage] = useState(image); // State to hold the selected image
+ const [imageUpload, setImageUpload] = useState(null); // State to hold the uploaded image
+ const { user } = useUser();
+ const [loading, setLoading] = useState(false);
+ // Function to handle file input change
+ const handleUpload = async () => {
+ console.log(user);
+ setLoading(true);
+ try {
+ // Upload selectedImage to Firebase storage
+ const imageRef = ref(storage, `profile-picture/${user.user_ID}`); // Define the reference to the image
+ await uploadBytes(imageRef, imageUpload); // Upload the image bytes
+
+ // Get the download URL
+ const url = await getDownloadURL(imageRef);
+ // Call setImage with the download URL to update the image
+ updateProfilePicture(url, user.user_ID);
+ setImage(url);
+ setLoading(false);
+ onClose();
+ } catch (error) {
+ console.error("Error uploading image to Firebase storage:", error);
+ }
+ };
+
+ const handleImageChange = (event) => {
+ const file = event.target.files[0];
+
+ if (file) {
+ const reader = new FileReader();
+
+ reader.onload = (e) => {
+ // Ensure that the result is set to the selectedImage state
+ setSelectedImage(e.target.result);
+ setImageUpload(file); // Set the uploaded image in the state
+ };
+
+ // Read the file as a data URL
+ reader.readAsDataURL(file);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+ Update the Profile Picture
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload
+ {loading && (
+
+ )}
+
+
+ {/*
+
+ */}
+
+
+
+
+ );
+}
+
+ProfileModal.propTypes = {
+ open: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ image: PropTypes.string.isRequired,
+ setImage: PropTypes.func.isRequired,
+};
+
+export default ProfileModal;
diff --git a/src/layouts/profile/index.js b/src/layouts/profile/index.js
index c52dd76..eaec131 100644
--- a/src/layouts/profile/index.js
+++ b/src/layouts/profile/index.js
@@ -69,7 +69,11 @@ function Overview() {
{
+ if (pdfUrl.toLowerCase().includes("pdf")) {
+ return "pdf";
+ } else if (pdfUrl.toLowerCase().includes("xlsx")) {
+ return "xlsx";
+ } else if (pdfUrl.toLowerCase().includes("csv")) {
+ return "csv";
+ } else {
+ return "pdf";
+ }
+ };
+ const mapExtensionToColor = (extension) => {
+ switch (extension) {
+ case "pdf":
+ return "error";
+ case "xlsx":
+ return "success"; // Change to the desired color for xls
+ case "csv":
+ return "warning"; // Change to the desired color for csv
+ default:
+ return "text"; // Replace with your default color
+ }
+ };
+
const handleDownload = (pdf_Url) => {
if (pdf_Url) {
// Create an anchor element to trigger the download
@@ -65,88 +89,6 @@ export default function Data() {
};
return {
- rawData: [
- {
- id: 1,
- name: "Historic Estate",
- location: "Jaffna",
- date: "Sun, 03 Sep 2023 18:30:04 GMT",
- contactNumbers: ["0774698456", "0768596489"],
- price: "Rs.250000",
- },
- {
- id: 2,
- name: "Seaview Bungalow",
- location: "Trincomalee",
- date: "Wed, 30 Aug 2023 18:30:07 GMT",
- contactNumbers: ["0774698459", "0768596492"],
- price: "Rs.190000",
- },
- {
- id: 3,
- name: "Ancient Property",
- location: "Anuradhapura",
- date: "Wed, 30 Aug 2023 18:30:05 GMT",
- contactNumbers: ["0774698457", "0768596490"],
- price: "Rs.120000",
- },
- {
- id: 4,
- name: "Mountain View Property",
- location: "Kandy",
- date: "Wed, 30 Aug 2023 18:30:01 GMT",
- contactNumbers: ["0774698453", "0768596486"],
- price: "Rs.150000",
- },
- {
- id: 5,
- name: "Hillside Property",
- location: "Nuwara Eliya",
- date: "Thu, 24 Aug 2023 18:30:09 GMT",
- contactNumbers: ["0774698461", "0768596494"],
- price: "Rs.120000",
- },
- {
- id: 6,
- name: "Seaside Paradise",
- location: "Galle",
- date: "Sat, 19 Aug 2023 18:30:02 GMT",
- contactNumbers: ["0774698454", "0768596487"],
- price: "Rs.200000",
- },
- {
- id: 7,
- name: "Beachfront Villa",
- location: "Negombo",
- date: "Thu, 10 Aug 2023 18:30:03 GMT",
- contactNumbers: ["0774698455", "0768596488"],
- price: "Rs.180000",
- },
- {
- id: 8,
- name: "Riverside Land",
- location: "Matara",
- date: "Fri, 04 Aug 2023 18:30:08 GMT",
- contactNumbers: ["0774698460", "0768596493"],
- price: "Rs.80000",
- },
- {
- id: 9,
- name: "Lakefront Retreat",
- location: "Batticaloa",
- date: "Thu, 03 Aug 2023 18:30:06 GMT",
- contactNumbers: ["0774698458", "0768596491"],
- price: "Rs.150000",
- },
- {
- id: 10,
- name: "Prime Lands",
- location: "Colombo",
- date: "Sun, 30 Jul 2023 18:30:00 GMT",
- contactNumbers: ["0774698452", "0768596485"],
- price: "Rs.100000",
- },
- ],
columns: [
{ Header: "Title", accessor: "author", align: "left" },
{ Header: "Type", accessor: "function", align: "left" },
@@ -163,7 +105,12 @@ export default function Data() {
function: ,
status: (
-
+
),
employed: (
diff --git a/src/layouts/reports/graphs/graphdetails.js b/src/layouts/reports/graphs/graphdetails.js
index b361175..e40787b 100644
--- a/src/layouts/reports/graphs/graphdetails.js
+++ b/src/layouts/reports/graphs/graphdetails.js
@@ -1,21 +1,36 @@
-import React from "react";
+import React, { useState } from "react";
import { useParams } from "react-router-dom"; // For accessing route parameters
import { Container, Typography } from "@mui/material";
// Material Dashboard 2 React components
import MDBox from "components/MDBox";
-import data from "../data/reportsdata";
import MDButton from "components/MDButton";
-import { generateExcel } from "../reports";
+import { generateCSV, generateExcel } from "../reports";
import { CSVLink } from "react-csv";
-import Projects from "layouts/dashboard/components/Projects";
+// import Projects from "layouts/dashboard/components/Projects";
+import DataTable from "examples/Tables/DataTable";
+import data1 from "layouts/dashboard/components/Projects/data";
+import { useEffect } from "react";
+import { useUser } from "utils/userContext";
const GraphDetails = () => {
- const { rawData } = data();
+ const { user } = useUser();
+ const { landSale, houseSale, marriageProposals } = data1();
+ const dataMapping = {
+ "Land Sales": landSale,
+ "House Sales": houseSale,
+ "Marriage Proposals": marriageProposals,
+ };
+ const [isValidTitle, setIsValidTitle] = useState(false);
// Get the advertisement id from the URL
const { title } = useParams();
-
+ useEffect(() => {
+ if (title in dataMapping) {
+ setIsValidTitle(true);
+ }
+ }, [title]);
+ const selectedData = dataMapping[title];
// Include id in the dependency array to refetch when id changes
return (
@@ -23,17 +38,39 @@ const GraphDetails = () => {
{title}
-
-
- generateExcel(rawData, "uselessReport")}>
- Export to Excel
-
-
-
-
- Export to CSV
-
-
+ {isValidTitle && (
+
+
+
+ )}
+ {isValidTitle && (
+ <>
+
+ generateExcel(selectedData.rows, `${user.name}Report`, user.user_ID)}
+ >
+ Export to Excel
+
+
+
+
+ generateCSV(selectedData.rows, `${user.name}Report`, user.user_ID)}
+ >
+ Export to CSV
+
+
+
+ >
+ )}
);
};
diff --git a/src/layouts/reports/index.js b/src/layouts/reports/index.js
index 6d5f95e..a503d17 100644
--- a/src/layouts/reports/index.js
+++ b/src/layouts/reports/index.js
@@ -50,16 +50,6 @@ function Report() {
- {/*
- generateExcel(rawData, "uselessReport")}>
- Export to Excel
-
-
-
-
- Export to CSV
-
- */}
diff --git a/src/layouts/reports/reports.js b/src/layouts/reports/reports.js
index 8c6a434..4ae8a42 100644
--- a/src/layouts/reports/reports.js
+++ b/src/layouts/reports/reports.js
@@ -7,21 +7,77 @@ import { savePdf } from "api/report/saveReport";
import { storage } from "../../firebase";
import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
-export const generateCSV = (data, filename) => {
- const csvContent = "data:text/csv;charset=utf-8," + data.map((row) => row.join(",")).join("\n");
+export const generateCSV = async (data, filename, userID) => {
+ let csvContent = "data:text/csv;charset=utf-8,";
+ for (let i = 0; i < data.length; i++) {
+ for (let j = 0; j < data[i].length; j++) {
+ csvContent += data[i][j];
+ if (j !== data[i].length - 1) {
+ csvContent += ",";
+ }
+ }
+ if (i !== data.length - 1) {
+ csvContent += "\n";
+ }
+ }
+
const encodedUri = encodeURI(csvContent);
+
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", `${filename}.csv`);
document.body.appendChild(link);
link.click();
+
+ const csvBlob = new Blob([csvContent], { type: "text/csv" });
+ const csvRef = ref(storage, `Reports/${filename}.csv`);
+
+ try {
+ await uploadBytes(csvRef, csvBlob);
+ const downloadURL = await getDownloadURL(csvRef);
+ const response = await savePdf(downloadURL, userID, filename);
+
+ if (response && response.message) {
+ console.log("CSV uploaded successfully!");
+ } else {
+ console.error("Failed to upload CSV:", response.error);
+ }
+ } catch (error) {
+ console.error("An error occurred:", error);
+ }
};
-export const generateExcel = (data, filename) => {
+// Function to generate Excel
+export const generateExcel = async (data, filename, userID) => {
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
- XLSX.writeFile(wb, `${filename}.xlsx`);
+ const wbout = XLSX.write(wb, { bookType: "xlsx", type: "binary" });
+
+ const excelBlob = new Blob([s2ab(wbout)], { type: "application/octet-stream" });
+ const excelRef = ref(storage, `Reports/${filename}.xlsx`);
+
+ try {
+ await uploadBytes(excelRef, excelBlob);
+ const downloadURL = await getDownloadURL(excelRef);
+ const response = await savePdf(downloadURL, userID, filename);
+
+ if (response && response.message) {
+ console.log("Excel uploaded successfully!");
+ } else {
+ console.error("Failed to upload Excel:", response.error);
+ }
+ } catch (error) {
+ console.error("An error occurred:", error);
+ }
+};
+
+// Helper function to convert string to ArrayBuffer
+const s2ab = (s) => {
+ const buf = new ArrayBuffer(s.length);
+ const view = new Uint8Array(buf);
+ for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xff;
+ return buf;
};
// Function to generate PDF
diff --git a/src/layouts/upload/empty.gif b/src/layouts/upload/empty.gif
new file mode 100644
index 0000000..e546043
Binary files /dev/null and b/src/layouts/upload/empty.gif differ
diff --git a/src/layouts/upload/guestindex.js b/src/layouts/upload/guestindex.js
index 215a2e2..995e6f2 100644
--- a/src/layouts/upload/guestindex.js
+++ b/src/layouts/upload/guestindex.js
@@ -40,7 +40,7 @@ function GuestExtractor() {
useEffect(() => {
const timer = setTimeout(() => {
handleOpenModal();
- }, 10000); // 5000 milliseconds (5 seconds)
+ }, 20000); // 5000 milliseconds (5 seconds)
return () => {
clearTimeout(timer);
diff --git a/src/layouts/upload/inputImage.js b/src/layouts/upload/inputImage.js
index 3fc6c0e..185a21b 100644
--- a/src/layouts/upload/inputImage.js
+++ b/src/layouts/upload/inputImage.js
@@ -1,18 +1,21 @@
import React from "react";
import { useNavigate } from "react-router-dom";
-import { Container, Typography } from "@mui/material";
+import { Checkbox, Container, Typography } from "@mui/material";
import Card from "@mui/material/Card";
import MDButton from "components/MDButton";
-import { uploadImages } from "api/sendImg";
+import { uploadImages } from "api/advertisementextract/sendImg";
import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
import { useAppState } from "utils/userContext";
+import { useState } from "react";
+import Loading from "react-loading";
const ImageUploader = () => {
// const [selectedFiles, setSelectedFiles] = useState([]);
// const [imagePreviews, setImagePreviews] = useState([]);
// const [backendResponse, setBackendResponse] = useState([]);
+ const [loading, setLoading] = useState(false);
const { state } = useAppState();
const selectedFiles = state.selectedFiles;
const setSelectedFiles = state.setSelectedFiles;
@@ -72,15 +75,28 @@ const ImageUploader = () => {
const handleSubmit = async () => {
if (selectedFiles.length > 0) {
try {
+ setLoading(true);
const response = await uploadImages(selectedFiles);
console.log("Image upload response:", response);
+ setLoading(false);
setBackendResponse(response.message);
+ setSelectedFiles([]);
+ setImagePreviews([]);
} catch (error) {
console.error("Error uploading images:", error);
+ setLoading(false);
+ alert("Sorry. Server error from our side. Try Again in a few seconds");
}
+ } else {
+ alert("upload at least one image");
}
};
+ const [publish, setPublish] = useState(false);
+ const handlePublishChange = (e) => {
+ setPublish(e.target.checked);
+ };
+
return (
{
) : (
Drag and drop images here
- or
+ or
)}
@@ -126,10 +142,40 @@ const ImageUploader = () => {
Upload Images
+
+
+
+
Submit
+ {loading && (
+
+
+ Analyzing...
+
+ {/* */}
+
+
+ )}
{backendResponse.length > 0 && (
{backendResponse.map((responseItem, index) => (
@@ -164,9 +210,7 @@ const ImageUploader = () => {
Category: {responseItem[1]}
-
- Phone Numbers: {responseItem[2].join(", ")}
-
+ Phone Numbers: {responseItem[2]}
Price: {responseItem[3]}
diff --git a/src/layouts/upload/inputPDF.js b/src/layouts/upload/inputPDF.js
index 1203b74..88fad1d 100644
--- a/src/layouts/upload/inputPDF.js
+++ b/src/layouts/upload/inputPDF.js
@@ -1,13 +1,15 @@
import React from "react";
import { useNavigate } from "react-router-dom";
-import { Container, Switch, Typography } from "@mui/material";
+import { Checkbox, Container, Switch, Typography } from "@mui/material";
import Card from "@mui/material/Card";
import MDButton from "components/MDButton";
import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
-import { uploadPdfs } from "api/sendPdf"; // Replace with your API endpoint for PDF upload
+import { uploadPdfs } from "api/advertisementextract/sendPdf"; // Replace with your API endpoint for PDF upload
import { useAppState } from "utils/userContext";
+import { useState } from "react";
+import Loading from "react-loading";
const PDFUploader = () => {
// const [selectedFiles, setSelectedFiles] = useState([]);
@@ -22,6 +24,7 @@ const PDFUploader = () => {
const imageScan = state.imageScan;
const setImageScan = state.setImageScan;
const navigate = useNavigate();
+ const [loading, setLoading] = useState(false);
const handleFileChange = (event) => {
const files = event.target.files;
@@ -41,14 +44,25 @@ const PDFUploader = () => {
const handleSubmit = async () => {
if (selectedFiles.length > 0) {
try {
+ setLoading(true);
const response = await uploadPdfs(selectedFiles, imageScan); // Replace with your API call to upload PDFs
console.log("PDF upload response:", response);
+ setLoading(false);
setBackendResponse(response.message);
+ setSelectedFiles([]);
} catch (error) {
console.error("Error uploading PDFs:", error);
+ setLoading(false);
+ alert("Sorry. Server error from our side. Try Again in a few seconds");
}
+ } else {
+ alert("Please select atleast one PDF file to upload");
}
};
+ const [publish, setPublish] = useState(false);
+ const handlePublishChange = (e) => {
+ setPublish(e.target.checked);
+ };
return (
@@ -92,10 +106,39 @@ const PDFUploader = () => {
setImageScan(!imageScan)} />
+
+
+
+
Submit
+ {loading && (
+
+
+ Analyzing...
+
+
+
+ )}
{backendResponse.length > 0 && (
{backendResponse.map((responseItem, index) => (
@@ -113,12 +156,10 @@ const PDFUploader = () => {
{
- // Define the query parameter object with the locations
const queryParams = {
locations: responseItem[0].join(", "),
};
- // Navigate to the '/advertisement_map' route with query parameters
navigate(`/advertisement_map?locations=${queryParams.locations}`);
}}
>
@@ -130,9 +171,7 @@ const PDFUploader = () => {
Category: {responseItem[1]}
-
- Phone Numbers: {responseItem[2].join(", ")}
-
+ Phone Numbers: {responseItem[2]}
Price: {responseItem[3]}
diff --git a/src/layouts/upload/inputURL.js b/src/layouts/upload/inputURL.js
index c6786ca..c7246ff 100644
--- a/src/layouts/upload/inputURL.js
+++ b/src/layouts/upload/inputURL.js
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
-import { useNavigate } from "react-router-dom";
import { useAppState } from "utils/userContext";
// import LinearProgress from "@mui/material/LinearProgress";
@@ -9,12 +8,14 @@ import MDTypography from "components/MDTypography";
import MDInput from "components/MDInput";
import Card from "@mui/material/Card";
-import { sendUrlToBackend } from "api/sendUrl";
-import Loading from "components/Loading";
+import { sendUrlToBackend } from "api/advertisementextract/sendUrl";
+import Loading from "react-loading";
+import { CardContent, Checkbox, Grid, Modal } from "@mui/material";
+import emptyImage from "./empty.gif";
+import RenderResults from "./renderresults";
function InputURL() {
const [loading, setLoading] = useState(false);
- const navigate = useNavigate();
const { state } = useAppState();
const inputUrl = state.inputUrl;
const setInputUrl = state.setInputUrl;
@@ -40,18 +41,61 @@ function InputURL() {
setBackendResponse([]); // Clear previous results
// Send URL to backend
- sendUrlToBackend(inputUrl)
+ sendUrlToBackend(inputUrl, publish)
.then((responseData) => {
console.log("Response from backend:", responseData);
setBackendResponse(responseData.results); // Assuming 'results' is the key holding the array
+ if (responseData.results[4] === "Couldn't found a category") {
+ handleOpenModal();
+ }
})
.catch((error) => {
console.error("Error sending URL to backend:", error);
+ alert("Sorry. Server error from our side. Try Again in a few seconds");
})
.finally(() => {
setLoading(false); // Set loading to false after fetch operation is complete
});
};
+ const [isModalOpen, setIsModalOpen] = useState(false);
+
+ const handleOpenModal = () => {
+ setIsModalOpen(true);
+ };
+ const [publish, setPublish] = useState(false);
+ const handlePublishChange = (e) => {
+ setPublish(e.target.checked);
+ };
+
+ const handleCloseModal = () => {
+ setIsModalOpen(false);
+ };
+ const emptyModal = (
+
+
+
+
+
+
+ Oops ! We couldn't find a category for your advertisement.
+
+
+ Try another one
+
+
+
+
+
+
+
+
+
+
+ );
return (
@@ -74,6 +118,7 @@ function InputURL() {
elevation={3}
style={{ padding: "12px", alignItems: "center" }}
>
+ {emptyModal}
+
+
+
+
Analyze
@@ -115,61 +174,17 @@ function InputURL() {
{loading && (
-
-
Analyzing...
- {/*
*/}
-
+
+
+ Analyzing...
+
+
)}
{backendResponse.length > 0 && (
-
- Title: {backendResponse[0]}
-
- {/*
- Text: {backendResponse[1]}
- */}
-
- Summary: {backendResponse[2]}
-
-
- Keywords: {backendResponse[3].join(", ")}
-
-
- Category: {backendResponse[4]}
-
-
- Price: {backendResponse[5]}
-
-
- Contact: {backendResponse[6]}
-
- {backendResponse[7].length > 0 && (
-
-
-
- Locations: {backendResponse[7].join(", ")}
-
- {
- // Define the query parameter object with the locations
- const queryParams = {
- locations: backendResponse[7].join(", "),
- };
-
- // Navigate to the '/advertisement_map' route with query parameters
- navigate(`/advertisement_map?locations=${queryParams.locations}`);
- }}
- >
- View Locations
-
-
-
- )}
+
)}
diff --git a/src/layouts/upload/renderresults.js b/src/layouts/upload/renderresults.js
new file mode 100644
index 0000000..f1154da
--- /dev/null
+++ b/src/layouts/upload/renderresults.js
@@ -0,0 +1,249 @@
+import React from "react";
+import { useNavigate } from "react-router-dom";
+
+// import LinearProgress from "@mui/material/LinearProgress";
+import MDBox from "components/MDBox";
+import MDButton from "components/MDButton";
+import MDTypography from "components/MDTypography";
+import Card from "@mui/material/Card";
+import PropTypes from "prop-types";
+
+function RenderResults({ backendResponse }) {
+ const navigate = useNavigate();
+ let categoryFields;
+ if (backendResponse[4] === "Land Sales") {
+ categoryFields = (
+
+
+ Title: {backendResponse[0]}
+
+ {/*
+ Text: {backendResponse[1]}
+ */}
+
+ Description: {backendResponse[2]}
+
+ {/*
+ Keywords: {backendResponse[3].join(", ")}
+ */}
+
+ Category: {backendResponse[4]}
+
+
+ Price: {backendResponse[5]}
+
+ {backendResponse[9] && (
+
+ Number of Perches: {backendResponse[9]}
+
+ )}
+
+ Contact Numbers: {backendResponse[6]}
+
+ {backendResponse[8] && (
+
+
+ Contact Emails: {backendResponse[8].join(", ")}
+
+
+ )}
+ {backendResponse[11] && (
+
+
+ Special LandMarks: {backendResponse[11].join(", ")}
+
+
+ )}
+ {backendResponse[10] && (
+
+ Source: {backendResponse[10]}
+
+ )}
+
+ {backendResponse[7].length > 0 && (
+
+
+
+ Locations: {backendResponse[7].join(", ")}
+
+ {
+ // Define the query parameter object with the locations
+ const queryParams = {
+ locations: backendResponse[7].join(", "),
+ };
+
+ // Navigate to the '/advertisement_map' route with query parameters
+ navigate(`/advertisement_map?locations=${queryParams.locations}`);
+ }}
+ >
+ View Locations
+
+
+
+ )}
+
+ );
+ } else if (backendResponse[4] === "House Sales") {
+ categoryFields = (
+
+
+ Title: {backendResponse[0]}
+
+
+ Description: {backendResponse[2]}
+
+ {/*
+ Keywords: {backendResponse[3].join(", ")}
+ */}
+
+ Category: {backendResponse[4]}
+
+
+ Price: {backendResponse[5]}
+
+ {backendResponse[9] && (
+
+ Number of Rooms: {backendResponse[9]}
+
+ )}
+
+
+ Contact Numbers: {backendResponse[6]}
+
+ {backendResponse[8] && (
+
+ Contact Emails: {backendResponse[8]}
+
+ )}
+ {backendResponse[10] && (
+
+ Source: {backendResponse[10]}
+
+ )}
+ {backendResponse[7].length > 0 && (
+
+
+
+ Locations: {backendResponse[7].join(", ")}
+
+ {
+ // Define the query parameter object with the locations
+ const queryParams = {
+ locations: backendResponse[7].join(", "),
+ };
+
+ // Navigate to the '/advertisement_map' route with query parameters
+ navigate(`/advertisement_map?locations=${queryParams.locations}`);
+ }}
+ >
+ View Locations
+
+
+
+ )}
+
+ );
+ } else if (backendResponse[4] === "Marriage Proposals") {
+ categoryFields = (
+
+
+ Title: {backendResponse[0]}
+
+
+ Description: {backendResponse[2]}
+
+ {/*
+ Keywords: {backendResponse[3].join(", ")}
+ */}
+
+ Category: {backendResponse[4]}
+
+
+ Gender: {backendResponse[5]}
+
+
+ Age: {backendResponse[9]}
+
+
+ Profession: {backendResponse[11]}
+
+
+ Special Requirements: {backendResponse[12]}
+
+
+ Nationality: {backendResponse[13]}
+
+
+ Contact Numbers: {backendResponse[6]}
+
+ {backendResponse[8] && (
+
+ Contact Emails: {backendResponse[8]}
+
+ )}
+ {backendResponse[10] && (
+
+ Source: {backendResponse[10]}
+
+ )}
+ {backendResponse[7].length > 0 && (
+
+
+
+ Locations: {backendResponse[7].join(", ")}
+
+ {
+ // Define the query parameter object with the locations
+ const queryParams = {
+ locations: backendResponse[7].join(", "),
+ };
+
+ // Navigate to the '/advertisement_map' route with query parameters
+ navigate(`/advertisement_map?locations=${queryParams.locations}`);
+ }}
+ >
+ View Locations
+
+
+
+ )}
+
+ );
+ } else {
+ categoryFields = (
+
+
+ Title: {backendResponse[0]}
+
+
+ Description: {backendResponse[2]}
+
+ {/*
+ Keywords: {backendResponse[3].join(", ")}
+ */}
+
+ Category: {backendResponse[4]}
+
+
+ );
+ }
+
+ return
{categoryFields}
;
+}
+
+RenderResults.propTypes = {
+ // Add the missing prop type validations here
+ backendResponse: PropTypes.array, // It should be an array and required.
+
+ // Example for other missing validations:
+ backendResponseJoin: PropTypes.string, // If you have a prop for joining the array as a string
+ backendResponseLength: PropTypes.number, // If you have a prop for the array's length
+};
+
+export default RenderResults;
diff --git a/src/routes/adminroutes.js b/src/routes/adminroutes.js
index 05c55a2..efb02b3 100644
--- a/src/routes/adminroutes.js
+++ b/src/routes/adminroutes.js
@@ -1,8 +1,8 @@
// Material Dashboard 2 React layouts
import Dashboard from "layouts/dashboard";
-import Billing from "layouts/billing";
-import Notifications from "layouts/notifications";
+// import Billing from "layouts/billing";
+// import Notifications from "layouts/notifications";
import Profile from "layouts/profile";
import SignIn from "layouts/authentication/sign-in";
import SignUp from "layouts/authentication/sign-up";
@@ -23,6 +23,7 @@ import AdvertisementForm from "layouts/admin/submitadvertisement/submitad";
import UserView from "layouts/admin/manageuser/manageuser";
import ManageFeedback from "layouts/admin/managefeedback/feedback";
import ContentApprovalPage from "layouts/admin/contentapproval/contentApproval";
+import ManageReports from "layouts/admin/managereports/reportView";
// ...
@@ -97,7 +98,7 @@ const adminRoutes = [
key: "reportsview",
icon:
report,
route: "/managereports",
- component:
,
+ component:
,
},
{
type: "collapse",
@@ -107,14 +108,14 @@ const adminRoutes = [
route: "/managesupport",
component:
,
},
- {
- type: "collapse",
- name: "Billing",
- key: "billing",
- icon:
receipt_long,
- route: "/billing",
- component:
,
- },
+ // {
+ // type: "collapse",
+ // name: "Billing",
+ // key: "billing",
+ // icon:
receipt_long,
+ // route: "/billing",
+ // component:
,
+ // },
{
route: "/advertisement/:id",
component:
,
@@ -127,14 +128,14 @@ const adminRoutes = [
route: "/reports/:title",
component:
,
},
- {
- type: "collapse",
- name: "Notifications",
- key: "notifications",
- icon:
notifications,
- route: "/notifications",
- component:
,
- },
+ // {
+ // type: "collapse",
+ // name: "Notifications",
+ // key: "notifications",
+ // icon:
notifications,
+ // route: "/notifications",
+ // component:
,
+ // },
{
type: "collapse",
name: "Profile",
@@ -144,18 +145,18 @@ const adminRoutes = [
component:
,
},
{
- type: "collapse",
- name: "Sign In",
- key: "sign-in",
- icon:
login,
+ // type: "collapse",
+ // name: "Sign In",
+ // key: "sign-in",
+ // icon:
login,
route: "/authentication/sign-in",
component:
,
},
{
- type: "collapse",
- name: "Sign Up",
- key: "sign-up",
- icon:
assignment,
+ // type: "collapse",
+ // name: "Sign Up",
+ // key: "sign-up",
+ // icon:
assignment,
route: "/authentication/sign-up",
component:
,
},
diff --git a/src/routes/routes.js b/src/routes/routes.js
index ddac5b7..cf44131 100644
--- a/src/routes/routes.js
+++ b/src/routes/routes.js
@@ -24,6 +24,8 @@ import PropTypes from "prop-types";
import TBH from "layouts/TBI/tbi";
import FeedbackSection from "layouts/feedback/index";
import GuestExtractor from "layouts/upload/guestindex";
+import ResetPSW from "layouts/authentication/reset-password/cover";
+import NewPassword from "layouts/authentication/reset-password/cover/newpassword";
// ...
@@ -154,6 +156,14 @@ const routes = [
route: "/extractor",
component:
,
},
+ {
+ route: "/authentication/reset-password",
+ component:
,
+ },
+ {
+ route: "/authentication/new-password",
+ component:
,
+ },
{
route: "/reports/:title",
component:
,
diff --git a/src/utils/userContext.js b/src/utils/userContext.js
index 1aa013b..87c16d3 100644
--- a/src/utils/userContext.js
+++ b/src/utils/userContext.js
@@ -1,5 +1,6 @@
import React, { createContext, useContext, useState } from "react";
import PropTypes from "prop-types";
+import { updateLastSeen } from "api/updateUser/updateUser";
const UserContext = createContext();
const StateContext = createContext();
@@ -21,9 +22,14 @@ export const UserProvider = ({ children }) => {
setUser(userData);
};
- const logout = () => {
- setIsAuthenticated(false);
- setUser(null);
+ const logout = async () => {
+ try {
+ setIsAuthenticated(false);
+ setUser(null);
+ await updateLastSeen(user.user_ID); // Call the updateLastSeen function asynchronously
+ } catch (error) {
+ console.error("Error updating last seen status:", error);
+ }
};
const [inputUrl, setInputUrl] = useState("");