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

Org auth

parent b7114811
No related branches found
No related tags found
No related merge requests found
Showing
with 1530 additions and 8 deletions
...@@ -19,6 +19,10 @@ import MyOrganizations from "./components/myorg/MyOrganizations"; ...@@ -19,6 +19,10 @@ import MyOrganizations from "./components/myorg/MyOrganizations";
import OrganizationDetails from "./components/myorg/OrganizationDetails"; import OrganizationDetails from "./components/myorg/OrganizationDetails";
import NotFound from "./components/error/NotFound"; import NotFound from "./components/error/NotFound";
import OrganizationRoster from "./components/myorg/roster/OrganizationRoster"; import OrganizationRoster from "./components/myorg/roster/OrganizationRoster";
import OrganizationItems from "./components/myorg/items/OrganizationItems";
import OrganizationItemDetails from "./components/myorg/items/OrganizationItemDetails";
import OrganizationItemCreate from "./components/myorg/items/OrganizationItemCreate";
import OrganizationLocations from "./components/myorg/location/OrganizationLocations";
function App() { function App() {
// const [token, setToken] = useState(); // const [token, setToken] = useState();
...@@ -58,6 +62,18 @@ function App() { ...@@ -58,6 +62,18 @@ function App() {
<Route element={<PrivateRoutes token={token} />}> <Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/members" element={<OrganizationRoster token={token}/> } /> <Route path="/organizations/:orgId/members" element={<OrganizationRoster token={token}/> } />
</Route> </Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/items" element={<OrganizationItems token={token}/> } />
</Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/items/:itemId" element={<OrganizationItemDetails token={token}/> } />
</Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/items/create" element={<OrganizationItemCreate token={token}/> } />
</Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId/locations" element={<OrganizationLocations token={token}/> } />
</Route>
<Route path='*' element={<NotFound />}/> <Route path='*' element={<NotFound />}/>
<Route path='/404' element={<NotFound />}/> <Route path='/404' element={<NotFound />}/>
{/*<Route path="/organizations/:orgId" element={<OrganizationDetails token={token}/>}>*/} {/*<Route path="/organizations/:orgId" element={<OrganizationDetails token={token}/>}>*/}
......
...@@ -34,6 +34,10 @@ const OrganizationDetails = ({token}) => { ...@@ -34,6 +34,10 @@ const OrganizationDetails = ({token}) => {
// Redirect to the OrganizationMembers page // Redirect to the OrganizationMembers page
navigate(`/organizations/${orgId}/members`); navigate(`/organizations/${orgId}/members`);
}; };
const handleItemsButtonClick = () => {
// Redirect to the OrganizationMembers page
navigate(`/organizations/${orgId}/items`);
};
const handleLeaveButtonClick = async () => { const handleLeaveButtonClick = async () => {
if (window.confirm(`Are you sure you want to leave the organization: ${organization.name}?`)) { if (window.confirm(`Are you sure you want to leave the organization: ${organization.name}?`)) {
try { try {
...@@ -58,6 +62,10 @@ const OrganizationDetails = ({token}) => { ...@@ -58,6 +62,10 @@ const OrganizationDetails = ({token}) => {
} }
} }
const handleLocationButtonClick = () => {
navigate(`/organizations/${orgId}/locations`);
};
if (!organization) { if (!organization) {
return <div>Loading...</div>; return <div>Loading...</div>;
} }
...@@ -75,8 +83,8 @@ const OrganizationDetails = ({token}) => { ...@@ -75,8 +83,8 @@ const OrganizationDetails = ({token}) => {
<div className="button-container"> <div className="button-container">
<button className="blue-button" onClick={handleRosterButtonClick}>Roster</button> <button className="blue-button" onClick={handleRosterButtonClick}>Roster</button>
<button className="blue-button">Requests</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="blue-button" onClick={handleLocationButtonClick}>Locations</button>
<button className="dark-red-button" onClick={handleLeaveButtonClick}>Leave Organization</button> <button className="dark-red-button" onClick={handleLeaveButtonClick}>Leave Organization</button>
</div> </div>
</div> </div>
......
import React, { useState, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import Axios from 'axios';
import '../../user/Login.css'
const OrganizationItemCreate = ({ token }) => {
const { orgId } = useParams();
const navigate = useNavigate();
const [locations, setLocations] = useState([]);
const [formData, setFormData] = useState({
status: 'AVAILABLE',
category: 'TOOLS',
description: '',
name: '',
quantity: 0,
locationId: '',
});
const [error, setError] = useState(null); // New state for error handling
useEffect(() => {
const fetchLocations = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/location', {
orgId: parseInt(orgId),
jwt: token.jwt,
});
if (response.data.result === 'success') {
setLocations(response.data.data);
if (response.data.type === 'MEMBER')
{
//members are not supposed to create items, redirect them to 404 page
navigate('/404');
}
} else {
console.error('Error fetching locations');
}
} catch (error) {
console.error('Error fetching locations:', error);
}
};
fetchLocations();
}, [orgId, token]);
const handleDropdownChange = (field, value) => {
setFormData((prevData) => ({
...prevData,
[field]: value,
}));
};
const handleCreateItem = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/oneitem/create', {
orgId: parseInt(orgId),
jwt: token.jwt,
...formData,
});
if (response.data.result === 'success') {
navigate(`/organizations/${orgId}/items`);
} else {
console.error('Error creating item');
setError('Error, incomplete fields'); // Set error message
}
} catch (error) {
console.error('Some unexpected error occurred:', error);
setError('Error, incomplete fields'); // Set error message
}
};
return (
<div className="organization-item-create">
<h2>Create Item</h2>
<div className="create-item-fields">
<div>
<span>Status:</span>
<select value={formData.status} onChange={(e) => handleDropdownChange('status', e.target.value)}>
<option value="AVAILABLE">Available</option>
<option value="BORROWED">Borrowed</option>
</select>
</div>
<div>
<span>Category:</span>
<select value={formData.category} onChange={(e) => handleDropdownChange('category', e.target.value)}>
<option value="STATIONERY">Stationery</option>
<option value="MARKETING">Marketing</option>
<option value="ELECTRONICS">Electronics</option>
<option value="SUPPLIES">Supplies</option>
<option value="PERISHABLES">Perishables</option>
<option value="MERCHANDISE">Merchandise</option>
<option value="TOOLS">Tools</option>
<option value="CHEMICALS">Chemicals</option>
<option value="FLAMMABLE">Flammable</option>
<option value="OTHER">Other</option>
<option value="UNIQUE">Unique</option>
<option value="BOOKS">Books</option>
{/* Add other category options */}
</select>
</div>
<label>
Description:
<input
type="text"
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
/>
</label>
<label>
Name:
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
/>
</label>
<label>
Quantity:
<input
type="number"
value={formData.quantity}
onChange={(e) => setFormData({ ...formData, quantity: e.target.value })}
/>
</label>
<label>
Location:
<select
value={formData.locationId}
onChange={(e) => handleDropdownChange('locationId', e.target.value)}
>
<option value="">Select a location</option>
{locations.map(([locationName, locationId]) => (
<option key={locationId} value={locationId}>
{locationName}
</option>
))}
</select>
</label>
{error && <p className="error-message">{error}</p>}
</div>
<button onClick={handleCreateItem} className="create-item-button">
Create Item
</button>
</div>
);
};
export default OrganizationItemCreate;
/* OrganizationItemDetails.css */
.organization-item-details {
max-width: 600px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
align-items: center;
}
.item-details {
margin-top: 20px;
display: flex;
flex-direction: column;
align-items: center; /* Center the entire content */
text-align: center;
}
.item-details span {
display: block;
margin-bottom: 10px;
text-align: left;
width: 100%;
}
.modify-item-button {
display: block;
margin-top: 20px;
padding: 10px 20px;
color: #fff;
background-color: #5bc0de; /* Blue color for modify button */
border: 1px solid #5bc0de;
border-radius: 5px;
cursor: pointer;
}
.modify-item-button:hover {
background-color: #46b8da; /* Darker blue color on hover */
}
.delete-item-button {
background-color: #8b0000; /* Dark red color */
color: #fff;
border: 1px solid #6b0000; /* Dark red border color */
padding: 10px 20px;
font-size: 14px;
cursor: pointer;
border-radius: 5px;
margin-top: 20px;
}
.delete-item-button:hover
{
background-color: #6b0000; /* Dark red color on hover */
}
/* Style for dropdowns */
.item-details select {
padding: 8px;
width: 100%;
margin-bottom: 10px;
}
// OrganizationItemDetails.jsx
import React, { useState, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import Axios from 'axios';
import './OrganizationItemDetails.css';
import '../OrganizationDetails.css'
const OrganizationItemDetails = ({ token }) => {
const { orgId, itemId } = useParams();
const [itemInfo, setItemInfo] = useState(null);
const [locations, setLocations] = useState([]);
const [modifiedLocation, setModifiedLocation] = useState('');
const [modifiedFields, setModifiedFields] = useState({
status: '',
category: '',
description: '',
name: '',
quantity: 0,
});
const navigate = useNavigate();
const [error, setError] = useState(null); // New state for error handling
const handleDeleteItem = async () => {
// Logic to handle item deletion
if (
window.confirm(
`Are you sure you want to permanently delete all quantities of ${itemInfo.data[1]}? This will delete the entire item.`
)
) {
console.log('Deleting item...');
try {
const response = await Axios.post('http://localhost:8080/item/user/oneitem/delete', {
orgId: parseInt(orgId), // Convert orgId to integer
jwt: token.jwt,
itemId: parseInt(itemId), // Convert itemId to integer
});
if (response.data.result === 'success') {
navigate(`/organizations/${orgId}/items`);
} else {
console.error('Error deleting item');
}
} catch (error) {
console.error('Some unexpected error occurred:', error);
}
}
};
const handleDropdownChange = (field, value) => {
setModifiedFields((prevFields) => ({
...prevFields,
[field]: value,
}));
};
const handleModifyItem = async () => {
// Logic to handle item modification
try {
const modifiedFieldsToSend = {
orgId: parseInt(orgId),
jwt: token.jwt,
itemId: parseInt(itemId),
...modifiedFields,
};
// Check if a modified field is left blank and use the current value from itemInfo
Object.keys(modifiedFields).forEach((key) => {
if (modifiedFields[key] === '') {
console.log(key);
if (key === 'status')
modifiedFieldsToSend[key] = itemInfo.data[6];
else if (key === 'quantity')
modifiedFieldsToSend[key] = itemInfo.data[4];
else if (key === 'category')
modifiedFieldsToSend[key] = itemInfo.data[5];
else if (key === 'name')
modifiedFieldsToSend[key] = itemInfo.data[1];
else if (key === 'description')
modifiedFieldsToSend[key] = itemInfo.data[2];
else if (key === 'location')
modifiedFieldsToSend[key] = itemInfo.data[9];
}
});
const response = await Axios.put('http://localhost:8080/item/user/oneitem', modifiedFieldsToSend);
if (response.data.result === 'success') {
// Reload the item details after modification
const fetchItemDetails = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/oneitem', {
orgId: parseInt(orgId), // Convert orgId to integer
jwt: token.jwt,
itemId: parseInt(itemId), // Convert itemId to integer
});
if (response.data.result === 'success') {
setItemInfo(response.data);
} else {
console.error('Error fetching item information');
}
} catch (error) {
console.error('Error fetching item information:', error);
}
};
fetchItemDetails();
} else {
console.error('Error modifying item');
}
} catch (error) {
console.error('Some unexpected error occurred:', error);
}
};
// Fetch item details on component mount
useEffect(() => {
const fetchLocations = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/location', {
orgId: parseInt(orgId),
jwt: token.jwt,
});
if (response.data.result === 'success') {
setLocations(response.data.data);
} else {
console.error('Error fetching locations');
}
} catch (error) {
console.error('Error fetching locations:', error);
}
};
fetchLocations();
const fetchItemDetails = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/oneitem', {
orgId: parseInt(orgId),
jwt: token.jwt,
itemId: parseInt(itemId),
});
if (response.data.result === 'success') {
setItemInfo(response.data);
} else {
console.error('Error fetching item information');
}
} catch (error) {
console.error('Error fetching item information:', error);
}
};
fetchItemDetails();
}, [orgId, itemId, token]);
if (!itemInfo) {
return <div>Loading...</div>;
}
return (
<div className="organization-item-details">
<h2>Item Details</h2>
<div className="item-details">
<span>Name: {itemInfo.data[1]}</span>
<span>Description: {itemInfo.data[2]}</span>
<span>Owner Email: {itemInfo.data[3]}</span>
<span>Quantity: {itemInfo.data[4]}</span>
<span>Category: {itemInfo.data[5]}</span>
<span>Status: {itemInfo.data[6]}</span>
<span>Location: {itemInfo.data[9]}</span>
</div>
{(itemInfo.type === 'OWNER' || itemInfo.type === 'MANAGER') && (
<div>
<h3>Modify Item</h3>
<div className="modify-item-fields">
<div>
<span>Status:</span>
<select value={modifiedFields.status} defaultValue={itemInfo.data[6]} onChange={(e) => handleDropdownChange('status', e.target.value)}>
<option value="AVAILABLE">Available</option>
<option value="BORROWED">Borrowed</option>
</select>
</div>
<div>
<span>Category:</span>
<select value={modifiedFields.category} defaultValue={itemInfo.data[5]} onChange={(e) => handleDropdownChange('category', e.target.value)}>
<option value="STATIONERY">Stationery</option>
<option value="MARKETING">Marketing</option>
<option value="ELECTRONICS">Electronics</option>
<option value="SUPPLIES">Supplies</option>
<option value="PERISHABLES">Perishables</option>
<option value="MERCHANDISE">Merchandise</option>
<option value="TOOLS">Tools</option>
<option value="CHEMICALS">Chemicals</option>
<option value="FLAMMABLE">Flammable</option>
<option value="OTHER">Other</option>
<option value="UNIQUE">Unique</option>
<option value="BOOKS">Books</option>
</select>
</div>
<label>
Description:
<input
type="text"
value={modifiedFields.description}
onChange={(e) => setModifiedFields({ ...modifiedFields, description: e.target.value })}
/>
</label>
<label>
Name:
<input
type="text"
value={modifiedFields.name}
onChange={(e) => setModifiedFields({ ...modifiedFields, name: e.target.value })}
/>
</label>
<label>
Quantity:
<input
type="number"
value={modifiedFields.quantity}
onChange={(e) => setModifiedFields({ ...modifiedFields, quantity: e.target.value })}
/>
</label>
</div>
<label>
Location:
<select
value={modifiedFields.locationId}
onChange={(e) => setModifiedFields( { ...modifiedFields, locationId:e.target.value})}
>
<option value="">Select a location</option>
{locations.map(([locationName, locationId], index) => (
<option key={locationId} value={locationId}>
{locationName}
</option>
))}
</select>
</label>
<button onClick={handleModifyItem} className="modify-item-button">
Modify Item
</button>
</div>
)}
{(itemInfo.type === 'OWNER' || itemInfo.type === 'MANAGER') && (
<button onClick={handleDeleteItem} className="delete-item-button">
Delete Item
</button>
)}
</div>
);
};
export default OrganizationItemDetails;
.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;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
background-color: #f0f0f0; /* Optional background color for the header */
}
.create-item-button {
display: block;
margin-top: 20px;
padding: 10px 20px;
color: #fff;
background-color: #5bc0de; /* Blue color for modify button */
border: 1px solid #5bc0de;
border-radius: 5px;
cursor: pointer;
width: 300px;
}
/* Add more styles as needed */
import React, { useState, useEffect } from 'react';
import Axios from 'axios';
import './OrganizationItems.css'
import './OrganizationItemDetails.css'
import {useNavigate, 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('');
const navigate = useNavigate();
const handleItemClick = (item) => {
navigate(`/organizations/${orgId}/items/${item}`);
};
const [type, setType] = useState(null);
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);
setType(response.data.type);
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');
navigate('/404');
}
} catch (error) {
console.error('Error fetching organization items:', error);
navigate('/404');
}
};
// 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);
};
const handleCreateButton = () => {
navigate(`/organizations/${orgId}/items/create`);
}
return (
<div className="organization-items">
<div className="header">
<h2>Organization Items</h2>
{(type === 'MANAGER' || type === 'OWNER') && <button className="create-item-button" onClick={() => handleCreateButton()}>
Create Item
</button>}
</div>
<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" onClick={() => handleItemClick(item[0])}>
<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;
.organization-locations {
max-width: 600px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.custom-ul {
list-style-type: none;
padding: 0;
}
.custom-li {
background-color: #f9f9f9;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.delete-button {
width: 20%;
padding: 8px;
background-color: #8b0000; /* Dark red color */
border: 1px solid #6b0000; /* Dark red border color */
border: none;
border-radius: 3px;
cursor: pointer;
}
.delete-button:hover {
background-color: #6b0000; /* Dark red color on hover */
}
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import Axios from 'axios';
import "./OrganizationLocation.css"
const OrganizationLocations = ({ token }) => {
const { orgId } = useParams();
const [locations, setLocations] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const [userType, setUserType] = useState('');
const [newLocation, setNewLocation] = useState('');
const [createVisible, setCreateVisible] = useState(false);
useEffect(() => {
const fetchLocations = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/location', {
orgId: parseInt(orgId),
jwt: token.jwt,
});
if (response.data.result === 'success') {
setLocations(response.data.data);
setUserType(response.data.type);
} else {
console.error('Error fetching locations');
}
} catch (error) {
console.error('Error fetching locations:', error);
}
};
fetchLocations();
}, [orgId, token]);
const handleDeleteLocation = async (locationId, locationName) => {
if (
window.confirm(`Are you sure you want to delete the location ${locationName}? This will also delete all the items at this location. Please be sure you want to do that.`)
) {
try {
const response = await Axios.post('http://localhost:8080/item/user/location/delete', {
orgId: parseInt(orgId),
jwt: token.jwt,
locationId: locationId,
});
if (response.data.result === 'success') {
// Update the locations list after deletion
setLocations(locations.filter(([_, id]) => id !== locationId));
} else {
console.error('Error deleting location');
}
} catch (error) {
console.error('Some unexpected error occurred:', error);
}
}
};
const handleCreateLocation = async () => {
try {
const response = await Axios.post('http://localhost:8080/item/user/location/create', {
orgId: parseInt(orgId),
jwt: token.jwt,
location: newLocation,
});
if (response.data.result === 'success') {
// Refresh the locations after creating a new one
setCreateVisible(false);
window.location.reload(false);
} else {
console.error('Error creating location');
}
} catch (error) {
console.error('Error creating location:', error);
}
};
const filteredLocations = locations.filter(([locationName]) =>
locationName.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<div className="organization-locations">
<h2>Organization Locations</h2>
{userType === 'OWNER' || userType === 'MANAGER' ? (
<div>
<button className="create-location-button" onClick={() => setCreateVisible(true)}>
Create Location
</button>
{createVisible === true && (
<div>
<input
type="text"
placeholder="Enter location name"
value={newLocation}
onChange={(e) => setNewLocation(e.target.value)}
/>
<button onClick={handleCreateLocation}>Enter</button>
</div>
)}
</div>
) : null}
<label>
Search Location:
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</label>
<ul className="custom-ul">
{filteredLocations.map(([locationName, locationId]) => (
<li key={locationId} className="custom-li">
{locationName}
{(userType === 'OWNER' || userType === 'MANAGER') && (
<button onClick={() => handleDeleteLocation(locationId, locationName)} className="delete-button">
Delete Location
</button>
)}
</li>
))}
</ul>
</div>
);
};
export default OrganizationLocations;
...@@ -56,7 +56,7 @@ VALUES ...@@ -56,7 +56,7 @@ VALUES
('johnsmith@example.com', 2, 'MEMBER'), ('johnsmith@example.com', 2, 'MEMBER'),
('johnsmith@example.com', 4, 'MANAGER'), ('johnsmith@example.com', 4, 'MANAGER'),
('alicedoe@example.com', 5, 'MEMBER'), ('alicedoe@example.com', 5, 'MEMBER'),
('emilyjohnson@example.com', 2, 'MEMBER'); ('emilyjohnson@example.com', 2, 'MANAGER');
# INSERT INTO ORGANIZATION_ROSTER(user_email, organization_id, type) # INSERT INTO ORGANIZATION_ROSTER(user_email, organization_id, type)
# VALUES # VALUES
...@@ -100,21 +100,42 @@ CREATE TABLE IF NOT EXISTS LOCATION ( ...@@ -100,21 +100,42 @@ CREATE TABLE IF NOT EXISTS LOCATION (
CONSTRAINT fk_organization_location FOREIGN KEY (organization_id) REFERENCES ORGANIZATION (organization_id) ON DELETE CASCADE CONSTRAINT fk_organization_location FOREIGN KEY (organization_id) REFERENCES ORGANIZATION (organization_id) ON DELETE CASCADE
); );
INSERT INTO LOCATION (location, organization_id)
VALUES
('Student Storage Unit 343', 2),
('Club Room Rack A', 2),
('Club Room Rack B', 2),
('Borrowed', 2);
CREATE TABLE IF NOT EXISTS ITEM ( CREATE TABLE IF NOT EXISTS ITEM (
item_id INT AUTO_INCREMENT, item_id INT AUTO_INCREMENT,
name VARCHAR(128) NOT NULL, name VARCHAR(128) NOT NULL,
description VARCHAR(256), description VARCHAR(256),
owner_email VARCHAR(128), owner_email VARCHAR(128),
quantity INT NOT NULL, quantity INT NOT NULL,
category VARCHAR(128), category ENUM('STATIONERY', 'MARKETING', 'ELECTRONICS', 'SUPPLIES', 'PERISHABLES', 'MERCHANDISE', 'TOOLS', 'CHEMICALS', 'FLAMMABLE', 'OTHER', 'UNIQUE', 'BOOKS'),
status ENUM('AVAILABLE', 'BORROWED', 'LISTED', 'SOLD') NOT NULL, status ENUM('AVAILABLE', 'BORROWED') NOT NULL,
location_id INT NOT NULL, location_id INT NOT NULL,
organization_id INT NOT NULL, organization_id INT NOT NULL,
PRIMARY KEY (item_id), PRIMARY KEY (item_id),
CONSTRAINT fk_location_item FOREIGN KEY (location_id) REFERENCES LOCATION (location_id), CONSTRAINT fk_location_item FOREIGN KEY (location_id) REFERENCES LOCATION (location_id),
CONSTRAINT fk_organiztion_item FOREIGN KEY (organization_id) REFERENCES ORGANIZATION (organization_id) ON DELETE CASCADE CONSTRAINT fk_organization_item FOREIGN KEY (organization_id) REFERENCES ORGANIZATION (organization_id) ON DELETE CASCADE
); );
INSERT INTO ITEM (name, description, owner_email, quantity, category, status, location_id, organization_id)
VALUES
('Chess Set 1', 'Standard chess set with board', 'chesssociety@example.com', 5, 'TOOLS', 'AVAILABLE', 1, 2),
('Chess Clock', 'Digital chess clock for tournaments', 'chesssociety@example.com', 2, 'ELECTRONICS', 'AVAILABLE', 2, 2),
('Chess Strategy Book', 'Guide to advanced chess strategies', 'chesssociety@example.com', 3, 'BOOKS', 'AVAILABLE', 3, 2),
('Chess Tactics Guide', 'Book on improving chess tactics', 'chesssociety@example.com', 4, 'BOOKS', 'AVAILABLE', 1, 2),
('Chess Magazine', 'Latest issue of chess magazine', 'chesssociety@example.com', 1, 'BOOKS', 'AVAILABLE', 2, 2),
('Chess Puzzle Set', 'Collection of challenging chess puzzles', 'chesssociety@example.com', 6, 'TOOLS', 'AVAILABLE', 3, 2),
('Chess Club T-Shirt', 'Official Chess Society T-Shirt', 'chesssociety@example.com', 10, 'MERCHANDISE', 'AVAILABLE', 1, 2),
('Chess Trophy', 'Tournament winner trophy', 'chesssociety@example.com', 1, 'UNIQUE', 'AVAILABLE', 2, 2),
('Chess Analysis Board', 'Board for analyzing game positions', 'chesssociety@example.com', 2, 'TOOLS', 'AVAILABLE', 3, 2),
('Chess Membership Card', 'Official membership card for Chess Society', 'chesssociety@example.com', 1, 'OTHER', 'AVAILABLE', 1, 2);
CREATE TABLE IF NOT EXISTS LISTING ( CREATE TABLE IF NOT EXISTS LISTING (
listing_id INT AUTO_INCREMENT, listing_id INT AUTO_INCREMENT,
item_id INT NOT NULL, item_id INT NOT NULL,
......
package com.example.accessingdatamysql.item;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public class CustomItemRepository {
@Autowired
private EntityManager entityManager;
@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 = :orgId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("orgId", orgId);
@SuppressWarnings("unchecked")
List<Object[]> resultList = query.getResultList();
return resultList;
}
@Transactional
public Object getItem(Integer orgId, Integer itemId)
{
try
{
String nativeQuery = "SELECT I.*, L.location FROM ITEM I JOIN LOCATION L ON I.location_id = L.location_id WHERE I.organization_id = :orgId AND I.item_id = :itemId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("orgId", orgId)
.setParameter("itemId", itemId);
return query.getSingleResult();
}
catch (Exception e)
{
return "Item Not Found";
}
}
@Transactional
public Object deleteItem(Integer itemId)
{
String nativeQuery = "DELETE FROM ITEM I WHERE I.item_id = :itemId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("itemId", itemId);
return query.executeUpdate();
}
@Transactional
public List<Object> getLocation(Integer orgId)
{
String nativeQuery = "SELECT L.location, L.location_id FROM LOCATION L WHERE L.organization_id = :orgId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("orgId", orgId);
return query.getResultList();
}
@Transactional
public Object deleteLocation(Integer locationId)
{
String nativeQuery = "DELETE FROM LOCATION L WHERE L.location_id = :locationId";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("locationId", locationId);
return query.executeUpdate();
}
@Transactional
public Object createLocation(String locationName, Integer orgId)
{
String nativeQuery = "INSERT INTO LOCATION(location, organization_id) VALUES (:locationName, :orgId)";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter("locationName", locationName)
.setParameter("orgId", orgId);
return query.executeUpdate();
}
@Transactional
public Object updateItem(Map<String, Object> json)
{
// Extract parameters from the JSON map
Integer itemId;
if (json.get("itemId") instanceof Integer)
itemId = (Integer) json.get("itemId");
else {
itemId = Integer.parseInt((String)json.get("itemId"));
}
Integer quantity;
if (json.get("quantity") instanceof Integer)
quantity = (Integer) json.get("quantity");
else {
quantity = Integer.parseInt((String)json.get("quantity"));
}
Integer locationId;
if (json.get("locationId") instanceof Integer)
locationId = (Integer) json.get("locationId");
else {
locationId = Integer.parseInt((String)json.get("locationId"));
}
String status = (String) json.get("status");
String description = (String) json.get("description");
String category = (String) json.get("category");
String name = (String) json.get("name");
// Use native SQL query with EntityManager to update the item
String nativeQuery = "UPDATE ITEM SET status = ?1, description = ?2, quantity = ?3, category = ?4, name = ?5, location_id = ?6 WHERE item_id = ?7";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter(1, status)
.setParameter(2, description)
.setParameter(3, quantity)
.setParameter(4, category)
.setParameter(5, name)
.setParameter(6, locationId)
.setParameter(7, itemId);
int updatedRows = query.executeUpdate();
return updatedRows > 0;
}
@Transactional
public Object createItem(Map<String, Object> json)
{
// Extract parameters from the JSON map
Integer orgId;
if (json.get("orgId") instanceof Integer)
orgId = (Integer) json.get("orgId");
else {
orgId = Integer.parseInt((String)json.get("orgId"));
}
Integer quantity;
if (json.get("quantity") instanceof Integer)
quantity = (Integer) json.get("quantity");
else {
quantity = Integer.parseInt((String)json.get("quantity"));
}
Integer locationId;
if (json.get("locationId") instanceof Integer)
locationId = (Integer) json.get("locationId");
else {
locationId = Integer.parseInt((String)json.get("locationId"));
}
String status = (String) json.get("status");
String description = (String) json.get("description");
String category = (String) json.get("category");
String name = (String) json.get("name");
// Use native SQL query with EntityManager to update the item
// Use native SQL query with EntityManager to create a new item
String ownerEmail = (String) entityManager.createNativeQuery("SELECT O.email FROM ORGANIZATION O WHERE O.organization_id = :orgId").setParameter("orgId", orgId).getSingleResult();
String nativeQuery = "INSERT INTO ITEM (name, description, owner_email, quantity, category, status, location_id, organization_id) " +
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)";
Query query = entityManager.createNativeQuery(nativeQuery)
.setParameter(1, name)
.setParameter(2, description)
.setParameter(3, ownerEmail)
.setParameter(4, quantity)
.setParameter(5, category)
.setParameter(6, status)
.setParameter(7, locationId)
.setParameter(8, orgId);
int updatedRows = query.executeUpdate();
return updatedRows > 0;
}
}
package com.example.accessingdatamysql.item;
import jakarta.persistence.*;
@Entity
@Table(name = "ITEM")
public class Item {
private String name;
private String description;
private String owner_email;
private Integer quantity;
public enum Category
{
STATIONERY,
MARKETING,
ELECTRONICS,
SUPPLIES,
PERISHABLES,
MERCHANDISE,
TOOLS,
CHEMICALS,
FLAMMABLE,
OTHER,
UNIQUE,
BOOKS,
}
@Enumerated(EnumType.STRING)
private Category category;
public enum Status
{
AVAILABLE,
BORROWED
}
@Enumerated(EnumType.STRING)
private Status status;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer locationId;
private Integer organizationId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOwner_email() {
return owner_email;
}
public void setOwner_email(String owner_email) {
this.owner_email = owner_email;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public Integer getLocationId() {
return locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
public Integer getOrganizationId() {
return organizationId;
}
public void setOrganizationId(Integer organizationId) {
this.organizationId = organizationId;
}
}
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 MyOrgRosterRepository myOrgRosterRepository;
@Autowired
private CustomItemRepository customItemRepository;
@Autowired
private UserRepository userRepository;
@PostMapping(path="/all")
public @ResponseBody Map<String, Object> getItems(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
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");
response.put("type", map.get("type"));
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/oneitem")
public @ResponseBody Map<String, Object> getItemToken(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("orgId") || !json.containsKey("jwt") || !json.containsKey("itemId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer orgId = 0;
Integer itemId;
if (json.get("orgId") instanceof Integer)
{
orgId = (Integer) json.get("orgId");
}
else
{
orgId = Integer.parseInt((String)(json.get("orgId"))); }
if (json.get("itemId") instanceof Integer)
itemId = (Integer) json.get("itemId");
else
itemId = Integer.parseInt((String)(json.get("itemId")));
response.put("data", customItemRepository.getItem(orgId, itemId));
response.put("result", "success");
response.put("type", map.get("type"));
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/oneitem/create")
public @ResponseBody Map<String, Object> createItemToken(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("orgId") || !json.containsKey("jwt") || !json.containsKey("name")
|| !json.containsKey("description") || !json.containsKey("quantity") || !json.containsKey("category")
|| !json.containsKey("status") || !json.containsKey("locationId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
if (map.get("type") != OrganizationRoster.Type.MANAGER && map.get("type") != OrganizationRoster.Type.OWNER)
{
response.put("result", "failure - not authorized, user cannot delete");
return response;
}
response.put("data", customItemRepository.createItem(json));
response.put("result", "success");
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/oneitem/delete")
public @ResponseBody Map<String, Object> deleteItemToken(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
System.out.println(json.entrySet());
if (!json.containsKey("orgId") || !json.containsKey("jwt") || !json.containsKey("itemId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
System.out.println(map.entrySet());
if (map.get("result").equals("success"))
{
Integer itemId;
if (map.get("type") != OrganizationRoster.Type.MANAGER && map.get("type") != OrganizationRoster.Type.OWNER)
{
response.put("result", "failure - not authorized, user cannot delete");
return response;
}
if (json.get("itemId") instanceof Integer)
itemId = (Integer) json.get("itemId");
else
itemId = Integer.parseInt((String)(json.get("itemId")));
response.put("data", customItemRepository.deleteItem(itemId));
response.put("result", "success");
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PutMapping(path="/user/oneitem")
public @ResponseBody Map<String, Object> updateItemToken(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("orgId") || !json.containsKey("jwt") || !json.containsKey("itemId") || !json.containsKey("name")
|| !json.containsKey("description") || !json.containsKey("quantity") || !json.containsKey("category")
|| !json.containsKey("status") || !json.containsKey("locationId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer itemId;
if (map.get("type") != OrganizationRoster.Type.MANAGER && map.get("type") != OrganizationRoster.Type.OWNER)
{
response.put("result", "failure - not authorized, user cannot delete");
return response;
}
if (json.get("itemId") instanceof Integer)
itemId = (Integer) json.get("itemId");
else
itemId = Integer.parseInt((String)(json.get("itemId")));
response.put("data", customItemRepository.updateItem(json));
response.put("result", "success");
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/location")
public @ResponseBody Map<String, Object> getLocation(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("jwt") || !json.containsKey("orgId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer orgId;
if (json.get("orgId") instanceof Integer)
orgId = (Integer) json.get("orgId");
else
orgId = Integer.parseInt((String)(json.get("orgId")));
response.put("data", customItemRepository.getLocation(orgId));
response.put("result", "success");
response.put("type", map.get("type"));
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/location/create")
public @ResponseBody Map<String, Object> createLocation(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("jwt") || !json.containsKey("orgId") || !json.containsKey("location"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer orgId;
if (json.get("orgId") instanceof Integer)
orgId = (Integer) json.get("orgId");
else
orgId = Integer.parseInt((String)(json.get("orgId")));
response.put("data", customItemRepository.createLocation((String)json.get("location"), orgId));
response.put("result", "success");
response.put("type", map.get("type"));
}
else
{
response.put("result", "failure - not authorized");
}
return response;
}
@PostMapping(path="/user/location/delete")
public @ResponseBody Map<String, Object> deleteLocation(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
if (!json.containsKey("jwt") || !json.containsKey("orgId") || !json.containsKey("locationId"))
{
response.put("result", "failure - bad request");
return response;
}
Map<String, Object> map = getUserOrg(json);
if (map.get("result").equals("success"))
{
Integer locationId;
if (json.get("locationId") instanceof Integer)
locationId = (Integer) json.get("locationId");
else
locationId = Integer.parseInt((String)(json.get("locationId")));
response.put("data", customItemRepository.deleteLocation(locationId));
response.put("result", "success");
response.put("type", map.get("type"));
}
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")));
}
}
package com.example.accessingdatamysql.item;
import org.springframework.data.repository.CrudRepository;
public interface ItemRepository extends CrudRepository<Item, Integer> {
}
...@@ -91,6 +91,15 @@ public class MyOrgRosterRepository implements OrgRosterRepository{ ...@@ -91,6 +91,15 @@ public class MyOrgRosterRepository implements OrgRosterRepository{
nativeQuery.setParameter("memberEmail", memberEmail); nativeQuery.setParameter("memberEmail", memberEmail);
int updatedRows = nativeQuery.executeUpdate(); int updatedRows = nativeQuery.executeUpdate();
if (type == OrganizationRoster.Type.OWNER)
{
String secondquery = "UPDATE ORGANIZATION SET owner_email = :memberEmail " +
"WHERE organization_id = :orgId ";
Query secondnativeQuery = entityManager.createNativeQuery(secondquery);
secondnativeQuery.setParameter("orgId", orgId);
secondnativeQuery.setParameter("memberEmail", memberEmail);
secondnativeQuery.executeUpdate();
}
result.put("result", "success"); result.put("result", "success");
result.put("updatedRows", updatedRows); result.put("updatedRows", updatedRows);
......
spring.jpa.hibernate.ddl-auto=update #spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/inventory spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/inventory
spring.datasource.username=root spring.datasource.username=root
spring.datasource.password=APbmCP70! spring.datasource.password=CSD@mysql-1872
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.jpa.show-sql: true #spring.jpa.show-sql: true
\ 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