Skip to content
Snippets Groups Projects
Commit d92022be authored by Sarthak Shrivastava's avatar Sarthak Shrivastava
Browse files

Added Organization Items list view, with filtering, searching etc.

parent 8841dad7
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,7 @@ import MyOrganizations from "./components/myorg/MyOrganizations";
import OrganizationDetails from "./components/myorg/OrganizationDetails";
import NotFound from "./components/error/NotFound";
import OrganizationRoster from "./components/myorg/roster/OrganizationRoster";
import OrganizationItems from "./components/myorg/items/OrganizationItems";
function App() {
// const [token, setToken] = useState();
......@@ -58,6 +59,9 @@ function App() {
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/members" element={<OrganizationRoster token={token}/> } />
</Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/items" element={<OrganizationItems token={token}/> } />
</Route>
<Route path='*' element={<NotFound />}/>
<Route path='/404' element={<NotFound />}/>
{/*<Route path="/organizations/:orgId" element={<OrganizationDetails token={token}/>}>*/}
......
......@@ -34,6 +34,10 @@ const OrganizationDetails = ({token}) => {
// Redirect to the OrganizationMembers page
navigate(`/organizations/${orgId}/members`);
};
const handleItemsButtonClick = () => {
// Redirect to the OrganizationMembers page
navigate(`/organizations/${orgId}/items`);
};
const handleLeaveButtonClick = async () => {
if (window.confirm(`Are you sure you want to leave the organization: ${organization.name}?`)) {
try {
......@@ -75,7 +79,7 @@ const OrganizationDetails = ({token}) => {
<div className="button-container">
<button className="blue-button" onClick={handleRosterButtonClick}>Roster</button>
<button className="blue-button">Requests</button>
<button className="blue-button">Items</button>
<button className="blue-button" onClick={handleItemsButtonClick}>Items</button>
<button className="blue-button">Listings</button>
<button className="dark-red-button" onClick={handleLeaveButtonClick}>Leave Organization</button>
</div>
......
.organization-items {
max-width: 800px;
margin: 0 auto;
}
h2 {
color: #333;
}
.filters {
margin-bottom: 20px;
}
label {
margin-right: 10px;
}
select,
input {
margin-right: 10px;
padding: 5px;
}
button {
padding: 5px 10px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
.items-list {
display: grid;
gap: 20px;
}
.item-item {
border: 1px solid #ddd;
padding: 15px;
border-radius: 8px;
background-color: #f9f9f9;
text-align: left;
}
.item-details {
display: flex;
flex-direction: column;
gap: 8px;
}
.item-details span {
display: block;
}
/* Add more styles as needed */
import React, { useState, useEffect } from 'react';
import Axios from 'axios';
import './OrganizationItems.css'
import {useParams} from "react-router-dom";
const OrganizationItems = ({ token }) => {
// const [orgId, setOrgId] = useState(null);
const [items, setItems] = useState([]);
const { orgId } = useParams();
const [filteredItems, setFilteredItems] = useState([]);
const [categories, setCategories] = useState([]);
const [locations, setLocations] = useState([]);
const [categoryFilter, setCategoryFilter] = useState('');
const [locationFilter, setLocationFilter] = useState('');
const [quantityFilter, setQuantityFilter] = useState('');
const [searchFilter, setSearchFilter] = useState('');
useEffect(() => {
const fetchData = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/all', {
orgId: orgId,
jwt: token.jwt,
});
if (response.data.result === 'success') {
setItems(response.data.data);
setFilteredItems(response.data.data);
// Extract categories and locations for filtering
const uniqueCategories = [...new Set(response.data.data.map(item => item[5]))];
const uniqueLocations = [...new Set(response.data.data.map(item => item[9]))];
setCategories(['', ...uniqueCategories]);
setLocations(['', ...uniqueLocations]);
} else {
console.error('Error fetching organization items');
}
} catch (error) {
console.error('Error fetching organization items:', error);
}
};
// Set orgId based on your logic (e.g., from token or passed as a prop)
// setOrgId(2);
fetchData();
}, [orgId, token]);
const handleFilter = () => {
let filteredItemsCopy = [...items];
// Apply filters
if (categoryFilter) {
filteredItemsCopy = filteredItemsCopy.filter(item => item[5] === categoryFilter);
}
if (locationFilter) {
filteredItemsCopy = filteredItemsCopy.filter(item => item[9] === locationFilter);
}
if (quantityFilter) {
filteredItemsCopy = filteredItemsCopy.filter(item => item[4] >= parseInt(quantityFilter, 10));
}
if (searchFilter) {
filteredItemsCopy = filteredItemsCopy.filter(item =>
item[1].toLowerCase().includes(searchFilter.toLowerCase())
);
}
setFilteredItems(filteredItemsCopy);
};
return (
<div className="organization-items">
<h2>Organization Items</h2>
<div className="filters">
<label>
Category:
<select onChange={(e) => setCategoryFilter(e.target.value)}>
{categories.map((category, index) => (
<option key={index} value={category}>{category}</option>
))}
</select>
</label>
<label>
Location:
<select onChange={(e) => setLocationFilter(e.target.value)}>
{locations.map((location, index) => (
<option key={index} value={location}>{location}</option>
))}
</select>
</label>
<label>
Minimum Quantity:
<input
type="number"
value={quantityFilter}
onChange={(e) => setQuantityFilter(e.target.value)}
/>
</label>
<label>
Search by Name:
<input
type="text"
value={searchFilter}
onChange={(e) => setSearchFilter(e.target.value)}
/>
</label>
<button onClick={handleFilter}>Apply Filters</button>
</div>
<div className="items-list">
{filteredItems.length > 0 ? (
filteredItems.map((item, index) => (
<div key={index} className="item-item">
<div className="item-details">
<span><strong>Name:</strong> {item[1]}</span>
<span><strong>Description:</strong> {item[2]}</span>
<span><strong>Owner Email:</strong> {item[3]}</span>
<span><strong>Quantity:</strong> {item[4]}</span>
<span><strong>Category:</strong> {item[5]}</span>
<span><strong>Status:</strong> {item[6]}</span>
<span><strong>Location:</strong> {item[9]}</span>
</div>
</div>
))
) : (
<p>No items found.</p>
)}
</div>
</div>
);
};
export default OrganizationItems;
......@@ -17,9 +17,9 @@ public class CustomItemRepository {
@Transactional
public List<Object[]> getAllItems(Integer orgId)
{
String nativeQuery = "SELECT I.*, L.location FROM ITEM I JOIN LOCATION L ON I.location_id = L.location_id WHERE I.organization_id = ?1";
String nativeQuery = "SELECT I.*, L.location FROM ITEM I JOIN LOCATION L ON I.location_id = L.location_id WHERE I.organization_id = :orgId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter(1, orgId);
.setParameter("orgId", orgId);
@SuppressWarnings("unchecked")
List<Object[]> resultList = query.getResultList();
......
package com.example.accessingdatamysql.item;
import com.example.accessingdatamysql.User;
import com.example.accessingdatamysql.UserRepository;
import com.example.accessingdatamysql.auth.AuthController;
import com.example.accessingdatamysql.myorg.MyOrgRosterRepository;
import com.example.accessingdatamysql.myorg.OrgRosterController;
import com.example.accessingdatamysql.myorg.OrgRosterRepository;
import com.example.accessingdatamysql.myorg.OrganizationRoster;
import jakarta.persistence.criteria.CriteriaBuilder;
import org.antlr.v4.runtime.misc.ObjectEqualityComparator;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@CrossOrigin
@RestController
@RequestMapping(path="/item")
public class ItemController {
@Autowired
private OrgRosterRepository orgRosterRepository;
private MyOrgRosterRepository myOrgRosterRepository;
@Autowired
private CustomItemRepository customItemRepository;
@GetMapping(path="/all")
public @ResponseBody Map<String, Object> getItems()
@Autowired
private UserRepository userRepository;
@PostMapping(path="/all")
public @ResponseBody Map<String, Object> getItems(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
response.put("data", customItemRepository.getAllItems(2));
System.out.println(json.entrySet());
if (!json.containsKey("orgId"))
{
response.put("result", "failure - bad request");
return response;
}
Integer orgId = 0;
if (json.get("orgId") instanceof Integer)
{
orgId = (Integer) json.get("orgId");
}
else
{
orgId = Integer.parseInt((String)(json.get("orgId")));
}
response.put("data", customItemRepository.getAllItems(orgId));
response.put("result", "success");
return response;
}
@PostMapping(path="/user/all")
public @ResponseBody Map<String, Object> getItemsToken(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
System.out.println(json.entrySet());
if (!json.containsKey("orgId") || !json.containsKey("jwt"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer orgId = 0;
if (json.get("orgId") instanceof Integer)
{
orgId = (Integer) json.get("orgId");
}
else
{
orgId = Integer.parseInt((String)(json.get("orgId")));
}
response.put("data", customItemRepository.getAllItems(orgId));
response.put("result", "success");
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
/*
Private helper function to validate that the user is supposed to see this data
*/
private @ResponseBody Map<String, Object> getUserOrg(Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("orgId") || !json.containsKey("jwt"))
{
response.put("result", "failed - bad request");
return response;
}
User found = new User();
AuthController au = new AuthController();
Map<String, String> res = au.verify(json); // if the jwt token could not be verified
if (res.containsKey("login") && res.get("login").equals("failed"))
{
response.put("result", "failed = bad token or bad request");
return response;
}
Optional<User> usr = userRepository.findById(res.get("user"));
if (!usr.isPresent())
{
response.put("result", "failed = user not found");
return response;
}
if (json.get("orgId") instanceof Integer)
return myOrgRosterRepository.findUserOrg(usr.get().getEmail(), (Integer) json.get("orgId"));
return myOrgRosterRepository.findUserOrg(usr.get().getEmail(), Integer.parseInt((String) json.get("orgId")));
}
}
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