Skip to content
Snippets Groups Projects
Commit 9740e76f authored by Sushant Dasari's avatar Sushant Dasari
Browse files

Merge branch 'SushantBranchConnectBackend' into 'main'

Sushant branch connect backend

See merge request !16
parents 8cebb97b a2f5c248
No related branches found
No related tags found
1 merge request!16Sushant branch connect backend
...@@ -20,6 +20,8 @@ import CreateUsers from "./components/CreateUsers/CreateUsers"; ...@@ -20,6 +20,8 @@ import CreateUsers from "./components/CreateUsers/CreateUsers";
import EditUserDetails from "./components/EditUserDetails/EditUserDetails"; import EditUserDetails from "./components/EditUserDetails/EditUserDetails";
import SearchUserForEdit from "./components/SearchUserForEdit/SearchUserForEdit"; import SearchUserForEdit from "./components/SearchUserForEdit/SearchUserForEdit";
import MyProfile from "./components/MyProfile/MyProfile"; import MyProfile from "./components/MyProfile/MyProfile";
import SearchBrowse from "./components/SearchBrowse/SearchBrowse";
import SearchBrowseResults from "./components/UserSearchResults/UserSearchResults";
function App() { function App() {
return ( return (
...@@ -44,6 +46,16 @@ function App() { ...@@ -44,6 +46,16 @@ function App() {
path="/admin/edit-person/:personId" path="/admin/edit-person/:personId"
element={<EditUserDetails />} element={<EditUserDetails />}
/> />
<Route
path="/user/search-results/:personId"
element={<SearchBrowseResults />}
/>
<Route
path="/user/search-browse"
element={<SearchBrowse />}
/>
<Route path="/practice" element={<PracticeHome />} /> <Route path="/practice" element={<PracticeHome />} />
<Route path="/AdminHome" element={<AdminHome />} /> <Route path="/AdminHome" element={<AdminHome />} />
<Route path="/MyAccountAdminView" element={<MyAccountAdminView />} /> <Route path="/MyAccountAdminView" element={<MyAccountAdminView />} />
......
import React, { useState } from "react"; import React, { useState } from "react";
import axios from "axios"; import axios from "axios";
import styles from "./CreateUsersStyles.module.css"; import styles from "./CreateUsersStyles.module.css";
// import * as XLSX from 'xlsx';
const CreateUsers = () => { const CreateUsers = () => {
const [option, setOption] = useState(""); const [option, setOption] = useState("");
...@@ -301,11 +300,11 @@ const CreateUsers = () => { ...@@ -301,11 +300,11 @@ const CreateUsers = () => {
</button> </button>
</form> </form>
); );
} else if (option === "xlsx") { } else if (option === "csv") {
return ( return (
<div className={styles.formContainer}> <div className={styles.formContainer}>
<h3>Upload Excel File</h3> <h3>Upload Excel File</h3>
<input type="file" accept=".xlsx" /> <input type="file" accept=".csv" />
<button type="submit" className={styles.submitButton}> <button type="submit" className={styles.submitButton}>
Upload Upload
</button> </button>
......
import React, { useState } from "react";
import axios from "axios";
import styles from "./SearchBrowse.module.css";
/*
Page to search users by multiple fields.
Once the search results are found, users can click into an
edit user details page.
*/
const SearchBrowse = () => {
const [searchParams, setSearchParams] = useState({
firstName: "",
middleName: "",
lastName: "",
nickName: "",
classYear: "",
gradYear: "",
gender: "",
techAlumniChapter: "",
degreeType: "",
degreeDepartment: "",
degreeCollege: "",
degreeYear: "",
involvement: "",
});
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleInputChange = (e) => {
const { name, value } = e.target;
setSearchParams((prev) => ({ ...prev, [name]: value }));
};
const handleSearch = async () => {
setLoading(true);
setError(null);
try {
const response = await axios.post(
`${process.env.REACT_APP_API_URL}/person/searchByName`,
{
...searchParams, // send all searchParams in the request payload
}
);
const filteredResults = filterAndSortResults(response.data.people, searchParams);
setResults(filteredResults);
} catch (err) {
setError(
err.response?.data?.message || "An error occurred during the search."
);
} finally {
setLoading(false);
}
};
const filterAndSortResults = (data, searchParams) => {
return data
.filter((person) => {
// Only keep results that match at least one non-empty field in searchParams
return Object.keys(searchParams).every((key) => {
return !searchParams[key] || person[key] === searchParams[key];
});
})
.sort((a, b) => {
// Sort by relevance based on number of matching fields
const relevanceA = calculateRelevance(a, searchParams);
const relevanceB = calculateRelevance(b, searchParams);
return relevanceB - relevanceA;
});
};
const calculateRelevance = (person, searchParams) => {
let relevance = 0;
Object.keys(searchParams).forEach((key) => {
if (searchParams[key] && person[key] === searchParams[key]) {
relevance += 1;
}
});
return relevance;
};
const handleDetailView = (personId) => {
window.location.href = `/user/search-results/${personId}`;
};
return (
<div className={styles.container}>
<h2>Search for person to view</h2>
{/* Search Form */}
<div className={styles.searchForm}>
<label>
First Name:
<input
type="text"
name="firstName"
value={searchParams.firstName}
onChange={handleInputChange}
/>
</label>
<label>
Middle Name:
<input
type="text"
name="middleName"
value={searchParams.middleName}
onChange={handleInputChange}
/>
</label>
<label>
Last Name:
<input
type="text"
name="lastName"
value={searchParams.lastName}
onChange={handleInputChange}
/>
</label>
<label>
Nickname:
<input
type="text"
name="nickName"
value={searchParams.nickName}
onChange={handleInputChange}
/>
</label>
<label>
Class Year:
<input
type="text"
name="classYear"
value={searchParams.classYear}
onChange={handleInputChange}
/>
</label>
<label>
Graduation Year:
<input
type="text"
name="gradYear"
value={searchParams.gradYear}
onChange={handleInputChange}
/>
</label>
<label>
Gender:
<input
type="text"
name="gender"
value={searchParams.gender}
onChange={handleInputChange}
/>
</label>
<label>
Tech Alumni Chapter:
<input
type="text"
name="techAlumniChapter"
value={searchParams.techAlumniChapter}
onChange={handleInputChange}
/>
</label>
<label>
Degree Type:
<input
type="text"
name="degreeType"
value={searchParams.degreeType}
onChange={handleInputChange}
/>
</label>
<label>
Degree Department:
<input
type="text"
name="degreeDepartment"
value={searchParams.degreeDepartment}
onChange={handleInputChange}
/>
</label>
<label>
Degree College:
<input
type="text"
name="degreeCollege"
value={searchParams.degreeCollege}
onChange={handleInputChange}
/>
</label>
<label>
Degree Year:
<input
type="text"
name="degreeYear"
value={searchParams.degreeYear}
onChange={handleInputChange}
/>
</label>
<label>
Involvement:
<input
type="text"
name="involvement"
value={searchParams.involvement}
onChange={handleInputChange}
/>
</label>
<button onClick={handleSearch} disabled={loading}>
{loading ? "Searching..." : "Search"}
</button>
</div>
{/* Results Section */}
{error && <p className={styles.error}>{error}</p>}
{!error && results.length === 0 && !loading && <p>No results found.</p>}
<ul className={styles.resultsList}>
{results.map((person) => (
<li
key={person.id}
className={styles.resultItem}
onClick={() => handleDetailView(person.peopleId)}
>
Name: {person.firstName} {person.middleName} {person.lastName} - Nickname: {person.nickName} - Chapter:{" "}
{person.techAlumniChapter} - Class year: {person.classYear} - Graduation Year: {person.gradYear} - Gender:{" "}
{person.gender} - Degree Type: {person.degreeType} - Degree Department: {person.degreeDepartment} - Degree College:{" "}
{person.degreeCollege} - Degree Year: {person.degreeYear} - Involvement: {person.involvement}
</li>
))}
</ul>
</div>
);
};
export default SearchBrowse;
.container {
max-width: 600px;
margin: 2rem auto;
padding: 1.5rem;
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
color: #333;
}
.searchForm {
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1.5rem;
}
label {
font-size: 1rem;
color: #555;
}
input {
padding: 0.5rem;
font-size: 1rem;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 0.3rem;
}
button {
padding: 0.7rem;
font-size: 1rem;
color: white;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #aaa;
cursor: not-allowed;
}
.resultsList {
list-style: none;
padding: 0;
}
.resultItem {
padding: 0.7rem;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 0.5rem;
background-color: #fff;
cursor: pointer;
transition: background-color 0.3s;
}
.resultItem:hover {
background-color: #f0f8ff;
}
.error {
color: #dc3545;
font-weight: bold;
}
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
import styles from "./UserSearchResults.module.css";
const UserSearchResults = () => {
const { personId } = useParams();
const [personInfo, setPersonInfo] = useState(null);
const [degrees, setDegrees] = useState([]);
const [involvements, setInvolvements] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchPersonDetails = async () => {
setLoading(true);
setError(null);
try {
const response = await axios.get(
`${process.env.REACT_APP_API_URL}/person/fullInfo/${personId}`
);
const { personInfo, degrees, involvements } = response.data.person;
setPersonInfo(personInfo);
setDegrees(degrees);
setInvolvements(involvements);
} catch (err) {
setError(err.response?.data?.message || "Failed to fetch user details.");
} finally {
setLoading(false);
}
};
fetchPersonDetails();
}, [personId]);
if (loading) return <p>Loading user details...</p>;
if (error) return <p className={styles.error}>{error}</p>;
return (
<div className={styles.container}>
<h2>User Details</h2>
<div>
<h3>Personal Information</h3>
{Object.entries(personInfo || {}).map(([key, value]) =>
key.toLowerCase().includes("id") ? null : (
<p key={key}>
<strong>{key.replace(/([A-Z])/g, " $1")}:</strong> {value || "N/A"}
</p>
)
)}
</div>
<div>
<h3>Degrees</h3>
{degrees.map((degree, index) => (
<div key={index} className={styles.listItem}>
{Object.entries(degree).map(([key, value]) =>
key.toLowerCase().includes("id") ? null : (
<p key={key}>
<strong>{key.replace(/([A-Z])/g, " $1")}:</strong> {value || "N/A"}
</p>
)
)}
</div>
))}
</div>
<div>
<h3>Involvements</h3>
{involvements.map((involvement, index) => (
<div key={index} className={styles.listItem}>
<p>{involvement || "N/A"}</p>
</div>
))}
</div>
</div>
);
};
export default UserSearchResults;
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 500px;
margin: 0 auto;
padding: 20px;
text-align: center;
border: 1px solid #ddd;
border-radius: 10px;
background-color: #f9f9f9;
}
.details {
margin-top: 15px;
}
.editButton, .saveButton, .deleteButton {
margin: 10px;
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.editButton {
background-color: #4CAF50;
color: white;
}
.saveButton {
background-color: #2196F3;
color: white;
}
.deleteButton {
background-color: #f44336;
color: white;
}
.confirmPopup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border: 1px solid #ddd;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.confirmButton {
background-color: #ee5b51;
color: white;
padding: 10px 15px;
margin: 5px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.cancelButton {
background-color: #ddd;
color: black;
padding: 10px 15px;
margin: 5px;
border: none;
border-radius: 5px;
cursor: pointer;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment