diff --git a/client/src/containers/Admin/Agreements/Agreements.css b/client/src/containers/Admin/Agreements/Agreements.css new file mode 100644 index 0000000..050cfdb --- /dev/null +++ b/client/src/containers/Admin/Agreements/Agreements.css @@ -0,0 +1,65 @@ +.agreements-wrapper { + max-width: 1200px; + margin: 40px auto; + padding: 0 20px; + font-family: Arial, sans-serif; +} + +h2 { + text-align: center; + margin-bottom: 20px; +} + +.table-container { + overflow-x: auto; + margin-bottom: 20px; +} + +.agreements-table { + width: 100%; + border-collapse: collapse; +} + +.agreements-table th, +.agreements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; +} + +.agreements-table th { + background-color: #f4f4f4; + position: sticky; + top: 0; + z-index: 1; +} + +.agreements-table tr:nth-child(even) { + background-color: #f9f9f9; +} + +.view-btn, +.agree-btn { + padding: 6px 12px; + background-color: #007bff; + border: none; + color: white; + border-radius: 4px; + cursor: pointer; + font-size: 0.9rem; +} + +.view-btn:hover, +.agree-btn:hover { + background-color: #0056b3; +} + +.home-link { + display: inline-block; + margin-top: 10px; + color: #007bff; +} + +.home-link:hover { + text-decoration: underline; +} diff --git a/client/src/containers/Admin/Agreements/Agreements.tsx b/client/src/containers/Admin/Agreements/Agreements.tsx index 227a586..9fc696c 100644 --- a/client/src/containers/Admin/Agreements/Agreements.tsx +++ b/client/src/containers/Admin/Agreements/Agreements.tsx @@ -1,122 +1,240 @@ -// import { Axios } from "axios"; +// // import { Axios } from "axios"; +// import React, { useEffect, useState } from "react"; +// // import PropTypes from 'prop-types' +// // import axios from "axios"; +// import { Link } from "react-router-dom"; + +// const Agreements = () => { +// // const url = "/api/agreement/create" +// const [agreement, setAgreement] = React.useState(false); +// const [agreeData, setData] = useState([]); + +// useEffect(() => { +// // Fix code to work in production +// // let letsClean = async () => +// fetch("/api/agreement/view") +// .then((res) => res.json()) +// .then((data) => { +// // console.log("Data is returned", data); +// // setAgreement(true); +// setAgreement(true); +// setData(data); +// // setData(data) +// // console.log(data[0].date) +// }) +// .catch((err) => err); +// // Fix code to work in production +// // return () => { +// // letsClean(); +// // }; +// // setAgreement(true); +// }, []); + +// useEffect(() => { +// const letsClean = () => { +// if (localStorage.getItem("agree") === "true") { +// setAgreement(true); +// // console.log(true); +// } else { +// setAgreement(false); +// // console.log(false); +// } +// }; +// return () => letsClean(); +// }, []); + +// const handleSubmit = (e: any) => { +// e.preventDefault(); +// localStorage.setItem("agree", "true"); +// setAgreement(true); +// console.log("agreed"); +// }; + +// const handleID = (e: any) => { +// e.preventDefault(); +// console.log("Do Something"); +// const id = e.target.value; +// // console.log(id) +// // axios.get(`/api/agreement/agreed/:${id}`) +// // fetch(`/api/agreement/agreed/${id}`) +// window.location.href = `/agreed/${id}`; +// // window.location.href=`http://localhost:3000/agreed/${id}`; +// }; + +// return agreement ? ( +//
+//

Show Agreements

+// +// +// +// +// {/* */} +// +// +// +// +// +// +// +// +// +// +// +// {agreeData.map((r: any, i: any) => ( +// +// +// {/* */} +// +// +// +// +// +// +// +// +// {/* */} +// +// ))} +// +//
IDEmailDate AgreedDescriptionNumber MCFreight RateInvoice RateCompanySignature
+// {" "} +// +// {r.id}{r.email}{r.date}{r.description}{r.numberMC}{r.freightRate}{r.invoiceRate}{r.company}{r.signature}{r}
+// {/* {agreeData.map((agree:any)=>(

{agree}

))} */} +// Home + +//
+// ) : ( +// <> +// +// No Agreements to show
+// Home +// +// ); +// }; + +// export default Agreements; + +// /* +// Agreements.propTypes = { +// text: PropTypes.string +// }; +// */ + import React, { useEffect, useState } from "react"; -// import PropTypes from 'prop-types' -// import axios from "axios"; import { Link } from "react-router-dom"; +import "./Agreements.css"; // Create a CSS file for styling -const Agreements = () => { - // const url = "/api/agreement/create" - const [agreement, setAgreement] = React.useState(false); - const [agreeData, setData] = useState([]); +interface Agreement { + id: string; + email: string; + date: string; + description: string; + numberMC?: string; + freightRate?: string; + invoiceRate?: string; + company?: string; + signature?: string; +} - useEffect(() => { - // Fix code to work in production - // let letsClean = async () => - fetch("/api/agreement/view") - .then((res) => res.json()) - .then((data) => { - // console.log("Data is returned", data); - // setAgreement(true); - setAgreement(true); - setData(data); - // setData(data) - // console.log(data[0].date) - }) - .catch((err) => err); - // Fix code to work in production - // return () => { - // letsClean(); - // }; - // setAgreement(true); - }, []); +const Agreements: React.FC = () => { + const [agreement, setAgreement] = useState(false); + const [agreeData, setAgreeData] = useState([]); + // Fetch agreements useEffect(() => { - const letsClean = () => { - if (localStorage.getItem("agree") === "true") { + const fetchAgreements = async () => { + try { + const res = await fetch("/api/agreement/view"); + const data = await res.json(); + setAgreeData(data); setAgreement(true); - // console.log(true); - } else { - setAgreement(false); - // console.log(false); + } catch (err) { + console.error(err); } }; - return () => letsClean(); + fetchAgreements(); + }, []); + + // Check local storage for agreement + useEffect(() => { + const storedAgree = localStorage.getItem("agree"); + if (storedAgree === "true") setAgreement(true); }, []); - const handleSubmit = (e: any) => { + const handleSubmit = (e: React.MouseEvent) => { e.preventDefault(); localStorage.setItem("agree", "true"); setAgreement(true); - console.log("agreed"); }; - const handleID = (e: any) => { - e.preventDefault(); - console.log("Do Something"); - const id = e.target.value; - // console.log(id) - // axios.get(`/api/agreement/agreed/:${id}`) - // fetch(`/api/agreement/agreed/${id}`) + const handleID = (id: string) => { window.location.href = `/agreed/${id}`; - // window.location.href=`http://localhost:3000/agreed/${id}`; }; - return agreement ? ( -
-

Show Agreements

- - - - - {/* */} - - - - - - - - - - - - {agreeData.map((r: any, i: any) => ( - - - {/* */} - - - - - - - - - {/* */} + if (!agreement) { + return ( +
+

Agreements

+

Please agree to continue:

+ +
+ Back to Home +
+ ); + } + + return ( +
+

Agreements

+ +
+
IDEmailDate AgreedDescriptionNumber MCFreight RateInvoice RateCompanySignature
- {" "} - - {r.id}{r.email}{r.date}{r.description}{r.numberMC}{r.freightRate}{r.invoiceRate}{r.company}{r.signature}{r}
+ + + + + + + + + + + - ))} - -
ActionEmailDate AgreedDescriptionNumber MCFreight RateInvoice RateCompanySignature
- {/* {agreeData.map((agree:any)=>(

{agree}

))} */} - Home + + + {agreeData.map((r) => ( + + + + + {r.email} + {r.date} + {r.description} + {r.numberMC || "—"} + {r.freightRate || "—"} + {r.invoiceRate || "—"} + {r.company || "—"} + {r.signature || "—"} + + ))} + + +
+ + Back to Home + - ) : ( - <> - - No Agreements to show
- Home - ); }; export default Agreements; - -/* -Agreements.propTypes = { - text: PropTypes.string -}; -*/ diff --git a/client/src/containers/Admin/Users/AllUsers.tsx b/client/src/containers/Admin/Users/AllUsers.tsx index 7ea76d5..d00ab9c 100644 --- a/client/src/containers/Admin/Users/AllUsers.tsx +++ b/client/src/containers/Admin/Users/AllUsers.tsx @@ -68,8 +68,199 @@ // export default AllUsers +// import React, { useEffect, useState } from "react"; +// import { Link, useNavigate } from "react-router-dom"; +// import axios from "axios"; +// import "./AllUsers.css"; + +// interface User { +// _id: string; +// email: string; +// password?: string; +// description?: string; +// archived?: boolean; +// admin?: boolean; +// developer?: boolean; +// } + +// const ITEMS_PER_PAGE = 10; + +// const AllUsers: React.FC = () => { +// const [users, setUsers] = useState([]); +// const [search, setSearch] = useState(""); +// const [archivedFilter, setArchivedFilter] = useState("all"); +// const [page, setPage] = useState(1); +// const navigate = useNavigate(); + +// // Fetch users +// const fetchUsers = async () => { +// try { +// const { data } = await axios.get("/api/user/view"); +// setUsers(data); +// } catch (error) { +// console.error("Error fetching users:", error); +// } +// }; + +// useEffect(() => { +// fetchUsers(); +// }, []); + +// // Filtered users +// const filteredUsers = users.filter((user) => { +// const matchesSearch = +// user.email?.toLowerCase().includes(search.toLowerCase()) || +// user.description?.toLowerCase().includes(search.toLowerCase()); +// const matchesArchived = +// archivedFilter === "all" || +// (archivedFilter === "archived" && user.archived) || +// (archivedFilter === "active" && !user.archived); +// return matchesSearch && matchesArchived; +// }); + +// // Pagination +// const startIndex = (page - 1) * ITEMS_PER_PAGE; +// const pageUsers = filteredUsers.slice( +// startIndex, +// startIndex + ITEMS_PER_PAGE +// ); +// const totalPages = Math.ceil(filteredUsers.length / ITEMS_PER_PAGE); + +// // Archive toggle +// const toggleArchive = async (id: string, current: boolean) => { +// try { +// await axios.put(`/api/user/archive/${id}`, { archived: !current }); +// setUsers((prev) => +// prev.map((u) => (u._id === id ? { ...u, archived: !current } : u)) +// ); +// } catch (error) { +// console.error("Error updating archive:", error); +// } +// }; + +// return ( +//
+//
+//

All Users

+//
+ +// {/* Search + Filter */} +//
+// setSearch(e.target.value)} +// /> +// +//
+ +// {/* Scrollable table */} +//
+// +// +// +// +// +// +// +// +// +// +// +// +// +// {pageUsers.length > 0 ? ( +// pageUsers.map((user) => ( +// +// +// +// +// +// +// +// +// +// )) +// ) : ( +// +// +// +// )} +// +//
Email (click to edit)PasswordDescriptionArchivedAdminDeveloperActions
+// +// {user.email} +// +// {user.password || "—"}{user.description || "—"} +// +// {user.archived ? "Archived" : "Active"} +// +// +// +// {user.admin ? "Yes" : "No"} +// +// +// +// {user.developer ? "Yes" : "No"} +// +// +// +//   +// +// Edit +// +//
+// No users found +//
+//
+ +// {/* Pagination */} +// {totalPages > 1 && ( +//
+// +// +// Page {page} of {totalPages} +// +// +//
+// )} + +// +// Back Home +// +//
+// ); +// }; + +// export default AllUsers; + import React, { useEffect, useState } from "react"; -import { Link, useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; import axios from "axios"; import "./AllUsers.css"; @@ -90,7 +281,6 @@ const AllUsers: React.FC = () => { const [search, setSearch] = useState(""); const [archivedFilter, setArchivedFilter] = useState("all"); const [page, setPage] = useState(1); - const navigate = useNavigate(); // Fetch users const fetchUsers = async () => { @@ -106,7 +296,7 @@ const AllUsers: React.FC = () => { fetchUsers(); }, []); - // Filtered users + // Filter users const filteredUsers = users.filter((user) => { const matchesSearch = user.email?.toLowerCase().includes(search.toLowerCase()) || @@ -126,7 +316,7 @@ const AllUsers: React.FC = () => { ); const totalPages = Math.ceil(filteredUsers.length / ITEMS_PER_PAGE); - // Archive toggle + // Toggle archive status const toggleArchive = async (id: string, current: boolean) => { try { await axios.put(`/api/user/archive/${id}`, { archived: !current }); @@ -140,9 +330,7 @@ const AllUsers: React.FC = () => { return (
-
-

All Users

-
+

All Users

{/* Search + Filter */}
@@ -177,11 +365,14 @@ const AllUsers: React.FC = () => { - {pageUsers.length > 0 ? ( + {pageUsers.length ? ( pageUsers.map((user) => ( - + {user.email} @@ -189,7 +380,9 @@ const AllUsers: React.FC = () => { {user.description || "—"} {user.archived ? "Archived" : "Active"} @@ -207,7 +400,9 @@ const AllUsers: React.FC = () => { @@ -235,7 +430,10 @@ const AllUsers: React.FC = () => { {/* Pagination */} {totalPages > 1 && (
- diff --git a/client/src/containers/Admin/Users/UserProfile/UserProfile.tsx b/client/src/containers/Admin/Users/UserProfile/UserProfile.tsx index 8c1dc57..aaf3fe6 100644 --- a/client/src/containers/Admin/Users/UserProfile/UserProfile.tsx +++ b/client/src/containers/Admin/Users/UserProfile/UserProfile.tsx @@ -229,6 +229,275 @@ // export default UserProfile; +// import React, { useEffect, useState } from "react"; +// import { useParams, useNavigate, Link } from "react-router-dom"; +// import axios from "axios"; +// import Button from "react-bootstrap/Button"; + +// interface User { +// email: string; +// password?: string; +// description?: string; +// } + +// const UserProfile: React.FC = () => { +// const { id } = useParams<{ id: string }>(); +// const navigate = useNavigate(); +// const [user, setUser] = useState({ email: "", password: "", description: "" }); +// const [loading, setLoading] = useState(true); +// const [error, setError] = useState(null); +// const [success, setSuccess] = useState(false); + +// // Fetch user by ID +// const fetchUser = async () => { +// try { +// const { data } = await axios.get(`/api/user/${id}`); +// setUser(data); +// } catch (err) { +// setError("Failed to fetch user."); +// console.error(err); +// } finally { +// setLoading(false); +// } +// }; + +// useEffect(() => { +// fetchUser(); +// }, [id]); + +// // Handle input changes +// const handleChange = (e: React.ChangeEvent) => { +// const { name, value } = e.target; +// setUser((prev) => ({ ...prev, [name]: value })); +// }; + +// // Handle form submit +// const handleSubmit = async (e: React.FormEvent) => { +// e.preventDefault(); +// try { +// await axios.put(`/api/user/update/${id}`, { +// email: user.email, +// password: user.password, +// description: user.description, +// }); +// setSuccess(true); +// setTimeout(() => navigate("/AllUsers"), 1000); +// } catch (err) { +// setError("Failed to update user."); +// console.error(err); +// } +// }; + +// if (loading) return

Loading user data...

; + +// return ( +//
+//

Update User

+// {error &&

{error}

} +// {success &&

User updated successfully!

} + +//
+//
+// +// +//
+ +//
+// +// +//
+ +//
+// +//