This commit is contained in:
string 2025-06-04 14:14:15 +05:30
parent 18231c4f44
commit 55c68917fc
42 changed files with 6399 additions and 2632 deletions

View File

@ -17,6 +17,7 @@
*/ */
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -136,7 +137,7 @@
</nav> </nav>
<!-- Header --> <!-- Header -->
<div <div
class="header bg-gradient-primary pb-8 pt-5 pt-lg-8 d-flex align-items-center" class="header pb-8 pt-5 pt-lg-8 d-flex align-items-center"
> >
<!-- Header container --> <!-- Header container -->
<div class="container-fluid"> <div class="container-fluid">
@ -157,7 +158,7 @@
<div class="container-fluid mt--7"> <div class="container-fluid mt--7">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-lg-4"> <div class="col-lg-4">
<div class="card bg-gradient-default text-center p-5"> <div class="card text-center p-5">
<a <a
href="https://demos.creative-tim.com/argon-dashboard-react/#/documentation/overview" href="https://demos.creative-tim.com/argon-dashboard-react/#/documentation/overview"
class="btn btn-white btn-icon mb-3 mb-sm-0" class="btn btn-white btn-icon mb-3 mb-sm-0"

View File

@ -1,9 +1,6 @@
{ {
"name": "authsec-dashboard-react", "name": "authsec-dashboard-react",
<<<<<<< HEAD
=======
"proxy": "http://157.66.191.31:33266", "proxy": "http://157.66.191.31:33266",
>>>>>>> 1c0592d (commit new code)
"version": "1.2.4", "version": "1.2.4",
"description": "React version of Argon Dashboard by Creative Tim", "description": "React version of Argon Dashboard by Creative Tim",
"main": "index.js", "main": "index.js",
@ -47,31 +44,32 @@
"not op_mini all" "not op_mini all"
], ],
"dependencies": { "dependencies": {
"@ant-design/icons": "^6.0.0",
"@cds/core": "^6.15.1", "@cds/core": "^6.15.1",
"@cds/react": "^6.15.1", "@cds/react": "^6.15.1",
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2", "@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@fortawesome/fontawesome-free": "6.5.1", "@fortawesome/fontawesome-free": "6.5.1",
"@fortawesome/fontawesome-svg-core": "^6.6.0", "@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@mui/material": "^6.4.8", "@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@mui/styled-engine": "^6.4.8", "@mui/styled-engine": "^6.4.8",
"@mui/styles": "^6.4.8", "@mui/styles": "^6.4.8",
"ajv": "^8.16.0", "ajv": "^8.16.0",
"antd": "^5.25.4",
"authsec-dashboard-react": "file:", "authsec-dashboard-react": "file:",
"axios": "^1.7.7", "axios": "^1.9.0",
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"bootstrap-icons": "^1.11.3", "bootstrap-icons": "^1.11.3",
"bootstrap-switch-button-react": "^1.2.0", "bootstrap-switch-button-react": "^1.2.0",
"chart.js": "^4.4.8", "chart.js": "^4.4.8",
"classnames": "2.3.2", "classnames": "2.3.2",
<<<<<<< HEAD
=======
"cors-anywhere": "^0.4.4", "cors-anywhere": "^0.4.4",
>>>>>>> 1c0592d (commit new code)
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"moment": "2.29.4", "moment": "2.29.4",
"multiselect-react-dropdown": "^2.0.25", "multiselect-react-dropdown": "^2.0.25",
@ -92,6 +90,7 @@
"react-hot-toast": "^2.4.1", "react-hot-toast": "^2.4.1",
"react-i18next": "^15.4.1", "react-i18next": "^15.4.1",
"react-icons": "^5.3.0", "react-icons": "^5.3.0",
"react-image-crop": "^11.0.10",
"react-pro-sidebar": "^1.1.0", "react-pro-sidebar": "^1.1.0",
"react-qr-reader": "^3.0.0-beta-1", "react-qr-reader": "^3.0.0-beta-1",
"react-router-dom": "6.21.1", "react-router-dom": "6.21.1",

View File

@ -20,7 +20,7 @@ apiClient.interceptors.request.use(
(config) => { (config) => {
const token = getToken(); const token = getToken();
if (token) { if (token) {
// console.log("token: ",token); console.log("token: ",token);
config.headers['Authorization'] = `Bearer ${token}`; config.headers['Authorization'] = `Bearer ${token}`;
} }
return config; return config;
@ -106,6 +106,18 @@ const apiService = {
.delete(url, options) // Pass options such as headers .delete(url, options) // Pass options such as headers
.catch(handleError), // Attach error handler .catch(handleError), // Attach error handler
}; };
// Add at the bottom of APIService.js
export const getSubmenuItems = async (id) => {
const response = await apiService.get(`/api1/submenu1/${id}`);
return response.data;
};
export const addSubmenuItem = async (menuId, submenuData) => {
const response = await apiService.post(`/api1/menu/${menuId}/submenu`, submenuData);
return response.data;
};
export const updateMenuItem = (id, formData) => apiService.put(`/api1/submenu1/${id}`, formData);
export const deleteMenuItem = (id) => apiService.delete(`/api1/menu/${id}`);
export default apiService; export default apiService;

View File

@ -24,27 +24,71 @@ export const fetchMenuItems = async () => {
} }
}; };
// export const addMenuItem = async (formData) => {
// try {
// const response = await apiService.post('/api1/Sec_menuDet', formData);
// console.log("add response: ",response.data);
// return response.data; // Return only the data part of the response
// } catch (error) {
// throw error; // Let the error be handled by the calling component
// }
// }
export const addMenuItem = async (formData) => { export const addMenuItem = async (formData) => {
try { try {
const response = await apiService.post('/api1/Sec_menuDet', formData); const payload = {
console.log("add response: ",response.data); menuItemDesc: formData.menuItemDesc,
return response.data; // Return only the data part of the response menuId: 0,
} catch (error) { itemSeq: formData.itemSeq || 0,
throw error; // Let the error be handled by the calling component moduleName: formData.moduleName || "",
main_menu_action_name: formData.main_menu_action_name || "#",
main_menu_icon_name: formData.main_menu_icon_name || "fa-circle",
status: formData.status === "true"
};
} console.log("Final payload:", payload);
}
// Remove the duplicate '/back' from the endpoint
const response = await apiService.post('/api1/Sec_menuDet/', payload);
return response.data;
} catch (error) {
console.error('Error adding menu item:', error);
throw error;
}
};
export const updateMenuItem = async (id, formData) => { export const updateMenuItem = async (id, formData) => {
try { try {
const response = await apiService.put(`/api1/submenu1/${id}`, formData); // Payload with ALL required fields (never change menuItemId)
console.log("update response: ",response.data); const payload = {
menuItemId: Number(id), // Keep original ID
menuItemDesc: formData.menuItemDesc,
menuId: formData.menuId || 0, // Keep original parent ID
itemSeq: formData.itemSeq || 0,
moduleName: formData.moduleName || "",
main_menu_action_name: formData.main_menu_action_name || "#",
main_menu_icon_name: formData.main_menu_icon_name || "fa-circle",
status: formData.status === "Enable" || formData.status === true
};
console.log("Updating menu item #"+id, payload);
// POST request with full payload (confirmed working)
const response = await apiService.post('/api1/Sec_menuDet/', payload);
console.log("Update successful:", response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Update failed:', {
id: id,
error: error.response?.data || error.message
});
throw error; throw error;
} }
} };
export const deleteMenuItem = async (id) => { export const deleteMenuItem = async (id) => {
@ -59,7 +103,9 @@ export const deleteMenuItem = async (id) => {
export const getSubmenuItems = async (id) => { export const getSubmenuItems = async (id) => {
try { try {
const response = await apiService.get(`/api1/submenu1/${id}`); const response = await apiService.get(`/api1/submenu1/${id}`);
console.log("get submenu response: ", response.data);
return response.data; // Return only the data part of the response return response.data; // Return only the data part of the response
} catch (error) { } catch (error) {
throw error; // Let the error be handled by the calling component throw error; // Let the error be handled by the calling component
@ -77,28 +123,135 @@ export const getSubmenuItems = async (id) => {
// } // }
export const addSubmenuItem = async (menuId, formData) => { // export const addSubmenuItem = async (menuId, formData) => {
// try {
// console.log("adding submenu item");
// console.log("menuid", menuId);
// const response = await apiService.post(`/api1/submenu1/${menuId}`, formData);
// console.log("menuid", menuId);
// console.log("add subMenu response: ", response.data);
// return response.data; // Return only the data part of the response
// } catch (error) {
// throw error; // Let the error be handled by the calling component
// }
// }
// Update the MenuMaintenanceAPI.js to handle single object
// export const addSubmenuItem = async (menuId, formData) => {
// try {
// // Convert string numbers to proper numbers
// const payload = {
// ...formData,
// menuItemId: Number(formData.menuItemId), // Convert to number
// itemSeq: Number(formData.itemSeq), // Convert to number
// menuId: Number(menuId) // Ensure parent ID is number
// };
// console.log("Final payload with converted numbers:", payload);
// const response = await apiService.put(`/api1/submenu1`, payload, { // Changed to POST
// headers: {
// 'Content-Type': 'application/json'
// }
// });
// // Verify the response contains all required fields
// if (!response.data?.menuItemId) {
// throw new Error("Incomplete response from server");
// }
// return response.data;
// } catch (error) {
// console.error("API Error Details:", {
// request: error.config?.data,
// response: error.response?.data
// });
// throw error;
// }
// };
export const addSubmenuItem = async (parentMenuId, formData) => {
try { try {
console.log("adding submenu item"); // Prepare payload - same structure as main menu but with parent ID relationship
console.log("menuid", menuId); const payload = {
menuItemDesc: formData.menuItemDesc,
menuId: Number(parentMenuId), // This establishes the parent-child relationship
itemSeq: formData.itemSeq || 0,
moduleName: formData.moduleName || "",
main_menu_action_name: formData.main_menu_action_name || "#",
main_menu_icon_name: formData.main_menu_icon_name || "fa-circle",
status: formData.status === "Enable" // Convert to boolean
};
const response = await apiService.post(`/api1/submenu1/${menuId}`, formData); console.log("Adding submenu with payload:", payload);
console.log("menuid", menuId);
console.log("add subMenu response: ", response.data); // Use the same endpoint as main menu
return response.data; // Return only the data part of the response const response = await apiService.post('/api1/Sec_menuDet/', payload);
return response.data;
} catch (error) { } catch (error) {
throw error; // Let the error be handled by the calling component console.error('Error adding submenu:', error);
throw error;
} }
} };
export const updateSubmenuItem = async (submenuId, formData) => {
const payload = {
menuItemId: Number(submenuId), // ID in the body
menuItemDesc: formData.menuItemDesc,
menuId: Number(formData.menuId), // Parent menu ID
itemSeq: formData.itemSeq || 0,
moduleName: formData.moduleName || "",
main_menu_action_name: formData.main_menu_action_name || "#",
main_menu_icon_name: formData.main_menu_icon_name || "fa-circle",
status: formData.status === "Enable" || formData.status === true
};
try {
const payload = {
menuItemId: Number(submenuId), // ID in the body
menuItemDesc: formData.menuItemDesc,
menuId: Number(formData.menuId), // Parent menu ID
itemSeq: formData.itemSeq || 0,
moduleName: formData.moduleName || "",
main_menu_action_name: formData.main_menu_action_name || "#",
main_menu_icon_name: formData.main_menu_icon_name || "fa-circle",
status: formData.status === "Enable" || formData.status === true
};
console.log("Updating submenu with payload:", payload);
// Using POST with ID in body (confirmed working)
const response = await apiService.post('/api1/Sec_menuDet/', payload);
return response.data;
} catch (error) {
console.error('Error updating submenu:', {
error: error.response?.data || error.message,
payload: payload
});
throw error;
}
};
export const deleteSubmenuItem = async (submenuId) => {
try {
console.log("Deleting submenu with ID:", submenuId);
// Using the working POST method with just menuItemId
const response = await apiService.post('/api1/Sec_menuDet/', {
menuItemId: Number(submenuId) // Only sending the ID as confirmed to work
});
console.log("Delete successful:", response.data);
return response.data;
} catch (error) {
console.error('Error deleting submenu:', {
status: error.response?.status,
error: error.response?.data || error.message,
submenuId: submenuId
});
throw error;
}
};

View File

@ -14,7 +14,7 @@ import "@fortawesome/fontawesome-free/css/all.min.css";
import "bootstrap-icons/font/bootstrap-icons.css"; import "bootstrap-icons/font/bootstrap-icons.css";
import "assets/scss/argon-dashboard-react.scss"; import "assets/scss/argon-dashboard-react.scss";
import About from "views/examples/about";
import AdminLayout from "layouts/Admin.js"; import AdminLayout from "layouts/Admin.js";
import AuthLayout from "layouts/Auth.js"; import AuthLayout from "layouts/Auth.js";
import Profile from "views/examples/Profile"; import Profile from "views/examples/Profile";
@ -30,7 +30,7 @@ import AccessTypeManagement from "components/Dashboard/AccessType";
import APIRegistry from "components/Dashboard/APIRegistry"; import APIRegistry from "components/Dashboard/APIRegistry";
import TOKENRegistry from "components/Dashboard/TOKENRegistry"; import TOKENRegistry from "components/Dashboard/TOKENRegistry";
import Error404 from "views/examples/Error404";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import Register from "views/examples/Register"; import Register from "views/examples/Register";
@ -60,6 +60,9 @@ import DashboardNewEdit from "./components/Dashboard/dashboardnew/DashboardnewEd
import EditNewDash from "components/Dashboard/dashboardnew/EditNewDash/EditNewDash"; import EditNewDash from "components/Dashboard/dashboardnew/EditNewDash/EditNewDash";
import ProtectedRoute from "ProtectedRoute"; import ProtectedRoute from "ProtectedRoute";
import DashboardRunner from "components/Dashboard/dashboardRunner/dashboardRunner"; import DashboardRunner from "components/Dashboard/dashboardRunner/dashboardRunner";
import Regform from "views/examples/regform";
import SequenceGenerator from "components/Dashboard/sequencegenerator";
// Inside <Routes>
const App = () => { const App = () => {
return ( return (
@ -90,22 +93,28 @@ const App = () => {
<AdminLayout /> <AdminLayout />
</ProtectedRoute> </ProtectedRoute>
}> }>
<Route path="regform" element={<Regform />} />
<Route path="error404" element={<Error404 />} />
<Route path="resetpassword" element={<ResetPassword />} />
<Route path="index" element={<Index/>}/> <Route path="index" element={<Index/>}/>
<Route path="profile" element={<Profile />} /> <Route path="profile" element={<Profile />} />
<Route path="user-report" element={<UserDetailsView />} /> <Route path="user-report" element={<UserDetailsView />} />
<Route path="setting" element={<SetupView />} /> <Route path="setting" element={<SetupView />} />
<Route path="resetpassword" element={<ResetPassword />} />
{/* Dynamic Routes */} {/* Dynamic Routes */}
<Route path="datamanagement" element={<DataManagement />} /> <Route path="datamanagement" element={<DataManagement />} />
<Route path="validationrule" element={<ValidationRule />} /> <Route path="validationrule" element={<ValidationRule />} />
<Route path="mappingrule" element={<MappingRule />} /> <Route path="mappingrule" element={<MappingRule />} />
<Route path="multidynmicbugs" element={<MultiDynamicBugs />} /> <Route path="multidynmicbugs" element={<MultiDynamicBugs />} />
<Route path="about" element={<About />} />
{/* Static Routes */} {/* Static Routes */}
<Route path="user-maintenance" element={<UserMaintenanceView />} /> <Route path="user-maintenance" element={<UserMaintenanceView />} />
<Route path="menu-access-control" element={<MenuAccessControl />} /> <Route path="menu-access-control" element={<MenuAccessControl />} />
<Route path="submenu/:menuItemId" element={<SubMenuMaintenance />} />
<Route path="sequence-generator" element={<SequenceGenerator />} />
<Route path="menu-access-control2" element={<MenuAccessControl2/>} /> <Route path="menu-access-control2" element={<MenuAccessControl2/>} />
<Route path="user-group-maintenance" element={<UserGroupMaintenance />} /> <Route path="user-group-maintenance" element={<UserGroupMaintenance />} />
<Route path="system-parameter" element={<SystemParameterForm />} /> <Route path="system-parameter" element={<SystemParameterForm />} />
<Route path="menu-maintenance" element={<MenuMaintenance />} /> <Route path="menu-maintenance" element={<MenuMaintenance />} />
@ -128,7 +137,7 @@ const App = () => {
<Route path="dashboard-new-edit/:id" element={<DashboardNewEdit/>}/> <Route path="dashboard-new-edit/:id" element={<DashboardNewEdit/>}/>
<Route path="edit-new-dash/:id" element={<EditNewDash/>}/> <Route path="edit-new-dash/:id" element={<EditNewDash/>}/>
<Route path="dashrunner/:id" element={<DashboardRunner/>}/> <Route path="dashrunner/:id" element={<DashboardRunner/>}/>
{/* buildercomponents */} {/* buildercomponents */}
@ -137,7 +146,6 @@ const App = () => {
<Route path="/auth/*" element={<AuthLayout />}> <Route path="/auth/*" element={<AuthLayout />}>
<Route path="login" element={<Login />} /> <Route path="login" element={<Login />} />
<Route path="register" element={<Register />} /> <Route path="register" element={<Register />} />
<Route path="resetpassword" element={<ResetPassword />} />
</Route> </Route>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>

View File

@ -931,6 +931,12 @@ pre code {
} }
@media (min-width: 576px) { @media (min-width: 576px) {
table input[type="checkbox"] {
position: static !important;
display: inline-block;
margin: auto;
}
.col-sm { .col-sm {
flex-basis: 0; flex-basis: 0;
flex-grow: 1; flex-grow: 1;
@ -1593,7 +1599,9 @@ pre code {
margin-left: 91.66667%; margin-left: 91.66667%;
} }
} }
.table-responsive {
overflow-x: auto;
}
.table { .table {
width: 100%; width: 100%;
margin-bottom: 1rem; margin-bottom: 1rem;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,99 @@
// components/ChartConfigModal.js
import React, { useState, useEffect } from 'react';
import {
Dialog, DialogTitle, DialogContent, DialogActions,
TextField, Checkbox, FormControlLabel, Button, MenuItem
} from '@mui/material';
const ChartConfigModal = ({
open,
onClose,
config,
onSave,
columns = []
}) => {
const [localConfig, setLocalConfig] = useState(config);
useEffect(() => {
setLocalConfig(config); // Reset on open
}, [config]);
const handleChange = (field, value) => {
setLocalConfig(prev => ({ ...prev, [field]: value }));
};
const handleSubmit = () => {
onSave(localConfig);
onClose();
};
return (
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
<DialogTitle>Configure Chart</DialogTitle>
<DialogContent>
<TextField
label="Chart Title"
fullWidth
value={localConfig.title}
onChange={e => handleChange('title', e.target.value)}
margin="dense"
/>
<FormControlLabel
control={
<Checkbox
checked={localConfig.showLegend}
onChange={e => handleChange('showLegend', e.target.checked)}
/>
}
label="Show Chart Legend"
/>
<FormControlLabel
control={
<Checkbox
checked={localConfig.showLabel}
onChange={e => handleChange('showLabel', e.target.checked)}
/>
}
label="Show Chart Label"
/>
<TextField
label="Table Name"
fullWidth
value={localConfig.tableName}
onChange={e => handleChange('tableName', e.target.value)}
margin="dense"
/>
<TextField
select
label="X-Axis"
fullWidth
value={localConfig.xAxis}
onChange={e => handleChange('xAxis', e.target.value)}
margin="dense"
>
{columns.map(col => (
<MenuItem key={col} value={col}>{col}</MenuItem>
))}
</TextField>
<TextField
select
label="Y-Axis"
fullWidth
value={localConfig.yAxis}
onChange={e => handleChange('yAxis', e.target.value)}
margin="dense"
>
{columns.map(col => (
<MenuItem key={col} value={col}>{col}</MenuItem>
))}
</TextField>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Cancel</Button>
<Button onClick={handleSubmit} variant="contained">Save</Button>
</DialogActions>
</Dialog>
);
};
export default ChartConfigModal;

View File

@ -168,7 +168,7 @@ function AccessTypeManagement() {
}; };
return ( return (
<div style={{marginTop:"11rem"}}> <div style={{marginTop:"1rem"}}>
{loading ? ( {loading ? (
<Spinner/> <Spinner/>
):( ):(

View File

@ -3,6 +3,13 @@
border-radius: 0.8rem; border-radius: 0.8rem;
} }
/* Ensures checkboxes behave like regular table content */
.table-responsive input[type="checkbox"] {
position: static !important;
margin: 0 auto;
display: block;
vertical-align: middle;
}
.thead-light{ .thead-light{
font-size: 1.1rem; font-size: 1.1rem;
@ -80,6 +87,7 @@
padding-top: 11rem; padding-top: 11rem;
padding-bottom: 5rem;/* Adjust as needed for the space between the navbar and component */ padding-bottom: 5rem;/* Adjust as needed for the space between the navbar and component */
margin-top: -10rem; margin-top: -10rem;
margin-right: 2rem;
} }

View File

@ -2,7 +2,7 @@
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); /* 4 columns */ grid-template-columns: repeat(4, 1fr); /* 4 columns */
gap: 15px; gap: 15px;
margin-top:9rem; margin-top:4rem;
margin-right: 2rem; margin-right: 2rem;
margin-left:2rem; margin-left:2rem;
margin-bottom:2rem; margin-bottom:2rem;
@ -19,7 +19,7 @@
} }
.usercard i { .usercard i {
color:#0E6591; color:rgba(255, 0, 0, 0.688);
} }
.usercard:hover{ .usercard:hover{
@ -28,7 +28,7 @@
} }
.usercard h3{ .usercard h3{
color: #0E6591; /* Change the card title color to red */ color: rgba(255, 0, 0, 0.739); /* Change the card title color to red */
font-family: 'GoogleFontName', sans-serif; font-family: 'GoogleFontName', sans-serif;
font-size: large; /* Apply the Google font */ font-size: large; /* Apply the Google font */
} }

View File

@ -184,7 +184,7 @@ const DynamicForm2 = () => {
); );
return ( return (
<div style={{ marginTop: "11rem" }}> <div style={{ marginTop: "7rem" }}>
{loading ? ( {loading ? (
<Spinner /> <Spinner />
) : ( ) : (

View File

@ -296,7 +296,7 @@ function DynamicFormAdd() {
return ( return (
<div style={{ marginTop: "11rem" }}> <div style={{ marginTop: "7rem" }}>
{loading ? ( {loading ? (
<Spinner/> <Spinner/>
) : ( ) : (

File diff suppressed because it is too large Load Diff

View File

@ -1240,10 +1240,12 @@ const MenuAccessControl = () => {
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
const data = await response.json(); console.log("data:", data); // Log the fetched data
setAlldata(data.items); setAlldata(data.items);
setPagination({ ...pagination, totalItems: data.totalItems }); setPagination({ ...pagination, totalItems: data.totalItems });
setLoading(false); // Stop loading setLoading(false); // Stop loading
const data = await response.json();
} catch (error) { } catch (error) {
console.error("Error fetching data:", error); console.error("Error fetching data:", error);
setLoading(false); // Stop loading in case of error setLoading(false); // Stop loading in case of error

View File

@ -18,7 +18,7 @@
// main_menu_action_name: true, // main_menu_action_name: true,
// status: true // status: true
// }); // });
// const [isSubMenu, setIsSubMenu] = useState(false); // const [dd, setIsSubMenu] = useState(false);
// const [parentMenuItemId, setParentMenuItemId] = useState(null); // const [parentMenuItemId, setParentMenuItemId] = useState(null);
// useEffect(() => { // useEffect(() => {
@ -70,7 +70,7 @@
// const handleSubmit = (event) => { // const handleSubmit = (event) => {
// event.preventDefault(); // event.preventDefault();
// if (isEditing) { // if (isEditing) {
// if (isSubMenu) { // if (dd) {
// setSubMenuItems(subMenuItems.map(item => // setSubMenuItems(subMenuItems.map(item =>
// item.menuItemId === currentMenuItem.menuItemId ? currentMenuItem : item // item.menuItemId === currentMenuItem.menuItemId ? currentMenuItem : item
// )); // ));
@ -80,7 +80,7 @@
// )); // ));
// } // }
// } else { // } else {
// if (isSubMenu) { // if (dd) {
// setSubMenuItems([...subMenuItems, { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` }]); // setSubMenuItems([...subMenuItems, { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` }]);
// } else { // } else {
// setMenuItems([...menuItems, { ...currentMenuItem, menuItemId: `ID-${menuItems.length + 1}` }]); // setMenuItems([...menuItems, { ...currentMenuItem, menuItemId: `ID-${menuItems.length + 1}` }]);
@ -301,18 +301,19 @@ import {
function MenuMaintenance() { function MenuMaintenance() {
const [menuItems, setMenuItems] = useState([]); const [menuItems, setMenuItems] = useState([]);
const [subMenuItems, setSubMenuItems] = useState([]); const [subMenuItems, setSubMenuItems] = useState([]);
const [showAddEditPopup, setShowAddEditPopup] = useState(false); const [showAddEditPopup, setShowAddEditPopup] = useState(false);
const [currentMenuItem, setCurrentMenuItem] = useState({ const [currentMenuItem, setCurrentMenuItem] = useState({
menuItemDesc: "", menuItemDesc: "",
menu_id: "", menuId: 0, // Important: Use menuId instead of menu_id
itemSeq: "", itemSeq: "",
moduleName: "", moduleName: "",
main_menu_action_name: "", main_menu_action_name: "",
main_menu_icon_name: "", main_menu_icon_name: "",
status: true, status: "true" // As string to match select input
}); });
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [recordsPerPage, setRecordsPerPage] = useState(10); const [recordsPerPage, setRecordsPerPage] = useState(10);
const [selectedMainMenuId, setSelectedMainMenuId] = useState(""); const [selectedMainMenuId, setSelectedMainMenuId] = useState("");
@ -390,6 +391,7 @@ function MenuMaintenance() {
console.log("Selected file:", file.name); // For debugging or processing console.log("Selected file:", file.name); // For debugging or processing
} }
}; };
const dd = isSubMenu; // or set based on your logic
const exportToExcel = () => { const exportToExcel = () => {
const worksheet = XLSX.utils.json_to_sheet([]); const worksheet = XLSX.utils.json_to_sheet([]);
@ -421,68 +423,93 @@ function MenuMaintenance() {
setSearchQuery(query); setSearchQuery(query);
}; };
const handleSubmit = async (event) => { // const handleSubmit = async (event) => {
event.preventDefault(); // event.preventDefault();
try { // try {
if (isEditing) { // if (isEditing) {
if (isSubMenu) { // if (isSubMenu) {
setSubMenuItems( // setSubMenuItems(
subMenuItems.map((item) => // subMenuItems.map((item) =>
item.menuItemId === currentMenuItem.menuItemId // item.menuItemId === currentMenuItem.menuItemId
? currentMenuItem // ? currentMenuItem
: item // : item
) // )
); // );
} else { // } else {
const formData = { // const formData = {
...currentMenuItem, // Include required fields for API payload // ...currentMenuItem, // Include required fields for API payload
}; // };
// Call the API to update the menu item // // Call the API to update the menu item
await updateMenuItem(currentMenuItem.menuItemId, formData); // await updateMenuItem(currentMenuItem.menuItemId, formData);
setMenuItems( // setMenuItems(
menuItems.map((item) => // menuItems.map((item) =>
item.menuItemId === currentMenuItem.menuItemId // item.menuItemId === currentMenuItem.menuItemId
? currentMenuItem // ? currentMenuItem
: item // : item
) // )
); // );
toast.success("Menu item updated successfully!"); // toast.success("Menu item updated successfully!");
} // }
} else { // } else {
if (isSubMenu) { // if (isSubMenu) {
// const formData = { // // const formData = {
// ...currentMenuItem, // Include fields required for submenu creation // // ...currentMenuItem, // Include fields required for submenu creation
// }; // // };
// const addedSubMenuItem = await addSubmenuItem(parentMenuItemId, formData); // // const addedSubMenuItem = await addSubmenuItem(parentMenuItemId, formData);
// setSubMenuItems([...subMenuItems, addedSubMenuItem]); // // setSubMenuItems([...subMenuItems, addedSubMenuItem]);
// toast.success("Submenu item added successfully!"); // // toast.success("Submenu item added successfully!");
// // Local addition for submenus // // // Local addition for submenus
// setSubMenuItems([ // // setSubMenuItems([
// ...subMenuItems, // // ...subMenuItems,
// { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` }, // // { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` },
// ]); // // ]);
} else { // } else {
// Prepare form data for API // // Prepare form data for API
const formData = { // const formData = {
...currentMenuItem, // Include required fields for API payload // ...currentMenuItem, // Include required fields for API payload
}; // };
// Call the API to add a new menu item // // Call the API to add a new menu item
const addedMenuItem = await addMenuItem(formData); // const addedMenuItem = await addMenuItem(formData);
// Update menu items with the newly added item from the API response // // Update menu items with the newly added item from the API response
setMenuItems([...menuItems, addedMenuItem]); // setMenuItems([...menuItems, addedMenuItem]);
toast.success("Menu item added successfully!"); // toast.success("Menu item added successfully!");
} // }
} // }
setShowAddEditPopup(false); // setShowAddEditPopup(false);
} catch (error) { // } catch (error) {
toast.error("There was an error while submitting the API."); // toast.error("There was an error while submitting the API.");
console.error("Error in handleSubmit:", error); // Log the error for debugging // console.error("Error in handleSubmit:", error); // Log the error for debugging
// }
// };
const handleSubmit = async (event) => {
event.preventDefault();
try {
if (isEditing) {
// Update existing item
const updatedItem = await updateMenuItem(currentMenuItem.menuItemId, currentMenuItem);
setMenuItems(menuItems.map(item =>
item.menuItemId === currentMenuItem.menuItemId ? updatedItem : item
));
toast.success("Menu item updated successfully!");
} else {
// Add new item
const addedItem = await addMenuItem(currentMenuItem);
setMenuItems([...menuItems, addedItem]);
toast.success("Menu item added successfully!");
} }
}; setShowAddEditPopup(false);
} catch (error) {
toast.error(`Operation failed: ${error.message}`);
console.error("Submit error:", error);
}
};
const handleDelete = async (menuItemId) => { const handleDelete = async (menuItemId) => {
if (isSubMenu) { if (isSubMenu) {
@ -502,7 +529,7 @@ function MenuMaintenance() {
const handleSubMenuClick = (menuItemId) => { const handleSubMenuClick = (menuItemId) => {
// Pehle navigate karke page open karein // Pehle navigate karke page open karein
navigate(`/admin/sub-menu-maintenance/:menuItemId`); navigate(`/admin/sub-menu-maintenance/${menuItemId}`);
// Phir API logic handle karein // Phir API logic handle karein
fetchSubMenuItems(menuItemId); fetchSubMenuItems(menuItemId);
@ -559,6 +586,8 @@ function MenuMaintenance() {
console.log("sliced menu", slicedMenus); // Verify the data in slicedMenus console.log("sliced menu", slicedMenus); // Verify the data in slicedMenus
return ( return (
<div style={{ marginTop: "-20px" }}> <div style={{ marginTop: "-20px" }}>
{loading ? ( {loading ? (
<Spinner /> <Spinner />
@ -597,6 +626,7 @@ function MenuMaintenance() {
padding: "10px 15px", padding: "10px 15px",
}} }}
> >
<FaSearch /> <FaSearch />
</InputGroup.Text> </InputGroup.Text>
<FormControl <FormControl
@ -693,7 +723,7 @@ function MenuMaintenance() {
/> />
</OverlayTrigger> </OverlayTrigger>
<OverlayTrigger {/* <OverlayTrigger
placement="bottom" placement="bottom"
overlay={<Tooltip>Menu Items</Tooltip>} overlay={<Tooltip>Menu Items</Tooltip>}
> >
@ -705,7 +735,7 @@ function MenuMaintenance() {
color: "#747264", color: "#747264",
}} }}
/> />
</OverlayTrigger> </OverlayTrigger> */}
</> </>
</Col> </Col>
</Row> </Row>
@ -757,7 +787,7 @@ function MenuMaintenance() {
) )
)} )}
<th>Actions</th> <th>Actions</th>
{!isSubMenu && <th>Sub-Menu</th>} {!dd && <th>Sub-Menu</th>}
</tr> </tr>
</thead> </thead>
@ -770,7 +800,7 @@ function MenuMaintenance() {
Object.keys(visibleColumns).filter( Object.keys(visibleColumns).filter(
(key) => visibleColumns[key] (key) => visibleColumns[key]
).length + ).length +
(isSubMenu ? 1 : 2) (dd ? 1 : 2)
} }
className="text-center" className="text-center"
> >
@ -830,7 +860,7 @@ function MenuMaintenance() {
}} }}
/> />
</td> </td>
{!isSubMenu && ( {!dd && (
<td className="text-center"> <td className="text-center">
<FontAwesomeIcon <FontAwesomeIcon
icon={faBars} icon={faBars}
@ -947,99 +977,151 @@ function MenuMaintenance() {
{/* Add/Edit Modal */} {/* Add/Edit Modal */}
{showAddEditPopup && ( {showAddEditPopup && (
<Modal <Modal
show={showAddEditPopup} show={showAddEditPopup}
onHide={() => setShowAddEditPopup(false)} onHide={() => setShowAddEditPopup(false)}
centered centered
> size="lg"
<Modal.Header> >
<Modal.Title> <Modal.Header>
{isEditing ? "Edit Menu Item" : "Add New Menu Item"} <Modal.Title>
</Modal.Title> {isEditing ? "Edit Menu Item" : "Add New Menu Item"}
<FontAwesomeIcon </Modal.Title>
icon={faTimes} <FontAwesomeIcon
size="lg" icon={faTimes}
onClick={handleClose} size="lg"
style={{ onClick={handleClose}
position: "absolute", style={{
top: "25px", position: "absolute",
right: "25px", top: "25px",
cursor: "pointer", right: "25px",
}} cursor: "pointer",
/> }}
</Modal.Header> />
<Modal.Body> </Modal.Header>
<Form onSubmit={handleSubmit}> <Modal.Body>
<Form.Group controlId="menuId" className="mb-3"> <Form onSubmit={handleSubmit}>
<Form.Label>menuId</Form.Label> <Row>
<Form.Control {/* Menu ID (Fixed at 0) */}
type="number" <Col md={6}>
name="menu_id" // Updated to match the state <Form.Group controlId="menuId" className="mb-3">
value={currentMenuItem.menu_id || ""} <Form.Label>Menu ID*</Form.Label>
onChange={handleInputChange} <Form.Control
required type="number"
className="custom-hover-border" name="menuId"
/> value={0}
</Form.Group> readOnly
<Form.Group controlId="menuItemDesc" className="mb-3"> plaintext
<Form.Label>Title</Form.Label> className="form-control-plaintext"
<Form.Control />
type="text" </Form.Group>
name="menuItemDesc" </Col>
value={currentMenuItem.menuItemDesc || ""}
onChange={handleInputChange} {/* Menu Item Name */}
required <Col md={6}>
className="custom-hover-border" <Form.Group controlId="menuItemDesc" className="mb-3">
/> <Form.Label>Menu Item Name*</Form.Label>
</Form.Group> <Form.Control
<Form.Group type="text"
controlId="main_menu_action_name" name="menuItemDesc"
className="mb-3" value={currentMenuItem.menuItemDesc || ""}
> onChange={handleInputChange}
<Form.Label>Link</Form.Label> required
<Form.Control />
type="text" </Form.Group>
name="main_menu_action_name" </Col>
value={currentMenuItem.main_menu_action_name || ""} </Row>
onChange={handleInputChange}
required <Row>
className="custom-hover-border" {/* Sequence */}
/> <Col md={6}>
</Form.Group> <Form.Group controlId="itemSeq" className="mb-3">
<Form.Group controlId="status" className="mb-3"> <Form.Label>Sequence</Form.Label>
<Form.Label>Status</Form.Label> <Form.Control
<Form.Select type="number"
name="status" name="itemSeq"
value={currentMenuItem.status ? "true" : "false"} value={currentMenuItem.itemSeq || ""}
onChange={handleInputChange} onChange={handleInputChange}
required />
className="custom-checkbox:checked" </Form.Group>
> </Col>
<option value="">Select Status</option>
<option value="true">Enable</option> {/* Module Name */}
<option value="false">Disable</option> <Col md={6}>
</Form.Select> <Form.Group controlId="moduleName" className="mb-3">
</Form.Group> <Form.Label>Module Name</Form.Label>
<Modal.Footer> <Form.Control
<Button type="text"
variant="primary" name="moduleName"
onClick={() => setShowAddEditPopup(false)} value={currentMenuItem.moduleName || ""}
className="custom_button" onChange={handleInputChange}
> />
Close </Form.Group>
</Button> </Col>
<Button </Row>
type="submit"
variant="primary" <Row>
className="custom_button" {/* Menu Action Link */}
> <Col md={6}>
{isEditing ? "Update Item" : "Add Item"} <Form.Group controlId="main_menu_action_name" className="mb-3">
</Button> <Form.Label>Menu Action Link</Form.Label>
</Modal.Footer> <Form.Control
</Form> type="text"
</Modal.Body> name="main_menu_action_name"
</Modal> value={currentMenuItem.main_menu_action_name || ""}
)} onChange={handleInputChange}
/>
</Form.Group>
</Col>
{/* Menu Icon Name */}
<Col md={6}>
<Form.Group controlId="main_menu_icon_name" className="mb-3">
<Form.Label>Menu Icon Name</Form.Label>
<Form.Control
type="text"
name="main_menu_icon_name"
value={currentMenuItem.main_menu_icon_name || ""}
onChange={handleInputChange}
placeholder="e.g., fa-home"
/>
</Form.Group>
</Col>
</Row>
{/* Status */}
<Form.Group controlId="status" className="mb-3">
<Form.Label>Status</Form.Label>
<Form.Select
name="status"
value={currentMenuItem.status ? "true" : "false"}
onChange={handleInputChange}
>
<option value="true">Enable</option>
<option value="false">Disable</option>
</Form.Select>
</Form.Group>
<Modal.Footer>
<Button
variant="secondary"
onClick={() => setShowAddEditPopup(false)}
className="me-2"
>
CANCEL
</Button>
<Button
type="submit"
variant="primary"
>
{isEditing ? "UPDATE" : "ADD"}
</Button>
</Modal.Footer>
</Form>
</Modal.Body>
</Modal>
)}
</div> </div>
)} )}
</div> </div>

View File

@ -322,78 +322,74 @@ const ReportBuild2All = () => {
{visibleColumns.action && <th className="text-center">Action</th>} {visibleColumns.action && <th className="text-center">Action</th>}
</tr> </tr>
</thead> </thead>
<tbody className="tbody"> <tbody className="tbody">
{filteredData.length === 0 ? ( {filteredData.length === 0 ? (
<tr> <tr>
<td <td
colSpan={ colSpan={Object.values(visibleColumns).filter(Boolean).length}
Object.values(visibleColumns).filter(Boolean).length className="text-center"
} >
className="text-center" No data available
> </td>
No data available
</td>
</tr>
) : (
filteredData.filter((user) => user.isSql === false).map((user) => (
<tr key={user.id}>
{visibleColumns.goTo && (
<td>
<Badge
color="primary"
pill
style={{
cursor: "pointer",
padding: "0.5em 1em",
fontSize: "0.9rem",
textTransform: "uppercase",
}}
onClick={() => goToLines(user)}
>
Set Up
</Badge>
</td>
)}
{visibleColumns.reportName && <td>{user.reportName}</td>}
{visibleColumns.description && <td>{user.description}</td>}
{visibleColumns.active && (
<td
style={{
fontWeight: user.active ? "bold" : "normal",
color: user.active ? "green" : "red",
backgroundColor: user.active
? "rgba(0, 128, 0, 0.1)"
: "rgba(255, 0, 0, 0.1)",
padding: "2px 4px",
display: "inline-block",
borderRadius: "4px",
textAlign: "center",
marginTop: "10px",
alignItems: "center",
justifyContent: "center",
}}
>
{user.active ? "Yes" : "No"}
</td>
)}
{visibleColumns.action && (
<td>
<FontAwesomeIcon
icon={faTrash}
onClick={(e) => confirmDelete(e, user)}
style={{
cursor: "pointer",
fontSize: "1rem",
color: "red",
marginRight: "15px",
}}
/>
</td>
)}
</tr> </tr>
)) ) : (
)} filteredData.filter(user => user.isSql === false).map(user => (
</tbody> <tr key={user.id}>
{visibleColumns.goTo && (
<td>
<Badge
color="primary"
pill
style={{
cursor: "pointer",
padding: "0.5em 1em",
fontSize: "0.9rem",
textTransform: "uppercase",
}}
onClick={() => goToLines(user)}
>
Set Up
</Badge>
</td>
)}
{visibleColumns.reportName && <td>{user.reportName}</td>}
{visibleColumns.description && <td>{user.description}</td>}
{visibleColumns.active && (
<td
style={{
fontWeight: user.active ? "bold" : "normal",
color: user.active ? "green" : "red",
backgroundColor: user.active ? "rgba(0, 128, 0, 0.1)" : "rgba(255, 0, 0, 0.1)",
padding: "2px 4px",
display: "inline-block",
borderRadius: "4px",
textAlign: "center",
marginTop: "10px",
}}
>
{user.active ? "Yes" : "No"}
</td>
)}
{visibleColumns.action && (
<td>
<FontAwesomeIcon
icon={faTrash}
onClick={(e) => confirmDelete(e, user)}
style={{
cursor: "pointer",
fontSize: "1rem",
color: "red",
marginRight: "15px",
}}
/>
</td>
)}
</tr>
))
)}
</tbody>
</Table> </Table>
)} )}

View File

@ -464,14 +464,16 @@ function UserDetailsView() {
responsive responsive
hover hover
className=" align-middle table-flush shadow-sm" className=" align-middle table-flush shadow-sm"
> >
<thead className="custom_header "> <thead className="custom_header ">
<tr> <tr>
<th className="text-center">Go To</th>
<th className="text-center">Report Name</th> <th className="text-center">Report Name</th>
<th className="text-center">Description</th> <th className="text-center">Description</th>
<th className="text-center">Status</th> <th className="text-center">Status</th>
<th className="text-center">Actions</th> <th className="text-center">Actions</th>
<th className="text-center">Go To</th>
</tr> </tr>
</thead> </thead>
<tbody className="tbody"> <tbody className="tbody">
@ -489,6 +491,20 @@ function UserDetailsView() {
style={{ cursor: "pointer" }} style={{ cursor: "pointer" }}
onClick={() => handleRowClick(detail)} onClick={() => handleRowClick(detail)}
> >
<td className="text-center">
<FontAwesomeIcon
icon={faCogs}
onClick={(e) => {
e.stopPropagation(); // Prevent row click event
handleGoTo(detail);
}}
style={{
cursor: "pointer",
fontSize: "1.2rem",
color: "#0E6591",
}}
/>
</td>
<td>{detail.reportName}</td> <td>{detail.reportName}</td>
<td>{detail.description || "No description available"}</td> <td>{detail.description || "No description available"}</td>
<td <td
@ -532,20 +548,7 @@ function UserDetailsView() {
}} }}
/> />
</td> </td>
<td className="text-center">
<FontAwesomeIcon
icon={faCogs}
onClick={(e) => {
e.stopPropagation(); // Prevent row click event
handleGoTo(detail);
}}
style={{
cursor: "pointer",
fontSize: "1.2rem",
color: "#0E6591",
}}
/>
</td>
</tr> </tr>
)) ))
)} )}

View File

@ -38,161 +38,60 @@ function SetupView({
<Spinner /> // Display the spinner while loading <Spinner /> // Display the spinner while loading
) : ( ) : (
<div className="usercards-container"> <div className="usercards-container">
<div className="usercards"> <div className="usercards">
<div <div className="usercard" onClick={() => navigate("/admin/user-maintenance")}>
className="usercard" <i className="fa fa-user-cog card-icon"></i>
onClick={() => { <h3>User Maintenance</h3>
console.log("User Maintenance card clicked"); <p>User Maintainance</p>
console.log("Navigating to:", "/admin/user-maintenance"); </div>
<div className="usercard" onClick={() => navigate("/admin/user-Group-Maintenance")}>
navigate("/admin/user-maintenance"); <i className="fa-solid fa-users"></i>
}} <h3>User Group Maintenance</h3>
// onClick={onUserMaintenanceClick} <p>User Group Maintenance</p>
> </div>
<i className="fa fa-user-cog card-icon"></i> <div className="usercard" onClick={() => navigate("/admin/menu-maintenance")}>
<h3>User Maintenance</h3> <i className="fa-solid fa-utensils"></i>
<p>Content for Card 1</p> <h3>Menu Maintenance</h3>
</div> <p>Menu Maintenance</p>
<div </div>
className="usercard" <div className="usercard" onClick={() => navigate("/admin/menu-access-control")}>
onClick={() => { <i className="fa-solid fa-lock"></i>
navigate("/admin/menu-access-control"); <h3>Menu Access Control</h3>
// navigate("/admin/menu-access-control2") <p>Menu Access Control</p>
}} </div>
> <div className="usercard" onClick={() => navigate("/admin/system-parameter")}>
<i className="fa-solid fa-lock"></i> <i className="fa-solid fa-gears"></i>
<h3>Menu Access Control</h3> <h3>System Parameter</h3>
<p>Content for Card 2</p> <p>System Parameter</p>
</div> </div>
<div className="usercard" onClick={() => { <div className="usercard" onClick={() => navigate("/admin/access-type")}>
navigate("/admin/user-Group-Maintenance"); <i className="fa-solid fa-key"></i>
}}> <h3>Access Type</h3>
<i className="fa-solid fa-users"></i> <p>Access Type</p>
<h3>User Group Maintenance</h3> </div>
<p>Content for Card 3</p> <div className="usercard" onClick={() => navigate("/admin/sequence-generator")}>
</div> <i className="fa-solid fa-list-ol"></i>
<div className="usercard" onClick={() => { <h3>Document Sequence</h3>
navigate("/admin/system-parameter"); <p>Manage document sequences</p>
}}> </div>
<i className="fa-solid fa-gears"></i> <div className="usercard" onClick={() => navigate("/admin/user-report")}>
<h3>System Parameter</h3> <i className="fa fa-file"></i>
<p>Content for Card 4</p> <h3>Reports</h3>
</div> <p>Reports Description</p>
<div className="usercard" onClick={() => { </div>
navigate("/admin/menu-maintenance"); <div className="usercard" onClick={() => navigate("/admin/api-registry")}>
}}> <i className="fas fa-database"></i>
<i className="fa-solid fa-utensils"></i> <h3>API Registry</h3>
<h3>Menu Maintenance</h3> <p>API Registry</p>
<p>Content for Card 5</p> </div>
</div> <div className="usercard" onClick={() => navigate("/admin/token-registry")}>
<div className="usercard" onClick={() => { <i className="fas fa-database"></i>
navigate("/admin/access-type"); <h3>Token Registry</h3>
}}> <p>Token Registry</p>
<i className="fa-solid fa-key"></i> </div>
<h3>Access Type</h3>
<p>Content for Card 6</p> </div>
</div> </div>
<div className="usercard" onClick={() => {
navigate("/admin/api-registry")
}}>
<i className="fas fa-database"></i>
<h3>API Registry</h3>
<p>Content for Card 7</p>
</div>
<div className="usercard" onClick={() => {
navigate("/admin/token-registry")
}}>
<i className="fas fa-key"></i>
<h3>Token Registry</h3>
<p>Content for Card 8</p>
</div>
{/* <div className="usercard" onClick={()=>{
navigate("/admin/datatype-1")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE1</h3>
<p>Content for Card 9</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/datatype-2")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE2</h3>
<p>Content for Card 10</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/datatype-3")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE3</h3>
<p>Content for Card 11</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/datatype-4")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE4</h3>
<p>Content for Card 12</p>
</div>
<div className="usercard"onClick={()=>{
navigate("/admin/datatype-5")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE5</h3>
<p>Content for Card 13</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/datatype-6")
}}>
<i className="fa fa-file"></i>
<h3>DATATYPE6</h3>
<p>Content for Card 14</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/basics-datatypes")
}}>
<i className="fa fa-file"></i>
<h3>Basics Datatypes</h3>
<p>Content for Card 15</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/advance-datatypes")
}}>
<i className="fa fa-file"></i>
<h3>Advanced Datatypes</h3>
<p>Content for Card 16</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/advance-datatypes2")
}}>
<i className="fa fa-file"></i>
<h3>Advanced Datatypes 2</h3>
<p>Content for Card 17</p>
</div>
<div className="usercard" onClick={()=>{
navigate("/admin/premium-datatypes")
}}>
<i className="fa fa-file"></i>
<h3>Premium Datatypes</h3>
<p>Content for Card 18</p>
</div> */}
<div className="usercard" onClick={() => {
navigate("/admin/user-report")
}}>
<i className="fa fa-file"></i>
<h3>Reports</h3>
<p>Report Description</p>
</div>
<div className="usercard" onClick={() => {
navigate("/admin/dynamic-form")
}}>
<i className="fa fa-file"></i>
<h3>DynamicForm</h3>
<p>Content for Card 16</p>
</div>
</div>
</div>
)} )}
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -144,15 +144,230 @@
// export default SystemParameterForm; // export default SystemParameterForm;
// import React, { useState, useEffect } from "react";
// import { Button, Form, Container, Row, Col } from "react-bootstrap";
// import "bootstrap/dist/css/bootstrap.min.css";
// import "../Dashboard/CSS/CSS/CommonStyle.css";
// import { toast } from "react-toastify";
// import Spinner from "../../UIComponants/Spinner";
// import {getSysParameter,addSysParameter} from "../../APIServices/SystemparameterApi";
// import { useSystemParameters } from "../../context/SystemParameterContext"; // update the path if needed
// const [loading, setLoading] = useState(true);
// const [formData, setFormData] = useState({
// schedulerTime: "",
// leaseTaxCode: "",
// vesselConfProcessLimit: "",
// rowToDisplay: "",
// linkToDisplay: "",
// rowToAdd: "",
// lovRowToDisplay: "",
// lovLinkToDisplay: "",
// oidserverName: "",
// oidBase: "",
// oidAdminUser: "",
// oidServerPort: "",
// userDefaultGroup: "",
// defaultDepartment: "",
// defaultPosition: "",
// singleCharge: "",
// firstDayOftheWeek: "",
// hourPerShift: "",
// cnBillingFrequency: "",
// billingDepartmentCode: "",
// basePriceList: "",
// nonContainerServiceOrder: "",
// ediMaeSchedulerONOFF: "",
// ediSchedulerONOFF: "",
// upload_Logo: null,
// company_Display_Name: "",
// });
// useEffect(() => {
// if (systemParameters) {
// setFormData((prevForm) => ({
// ...prevForm,
// ...systemParameters
// }));
// }
// }, [systemParameters]);
// const handleInputChange = (event) => {
// const { name, value } = event.target;
// setFormData((prevState) => ({
// ...prevState,
// [name]: value,
// }));
// };
// const handleFileChange = (event) => {
// setFormData((prevState) => ({
// ...prevState,
// logo: event.target.files[0],
// }));
// };
// // const handleSubmit = (event) => {
// // event.preventDefault();
// // toast.success("Form submitted successfully!");
// // // alert("Form submitted successfully!");
// // console.log("Form Data:", formData);
// // };
// const handleSubmit = async (event) => {
// event.preventDefault();
// try {
// console.log("Form Data:", formData);
// const sysParamData = await addSysParameter(formData);
// console.log("API Response:", sysParamData);
// toast.success("Form submitted successfully!");
// } catch (error) {
// console.error("Error:", error.response ? error.response.data : error.message);
// toast.error("Failed to submit the form. Please try again.");
// }
// };
// const handleClear = () => {
// setFormData({
// schedulerTimer: "",
// leaseTaxCode: "",
// vesselConfirmationProcessLimit: "",
// rowToDisplay: "",
// linkToDisplay: "",
// rowToAdd: "",
// lovRowToDisplay: "",
// lovLinkToDisplay: "",
// oldServerName: "",
// oldBase: "",
// oldAdminUser: "",
// oldServerPort: "",
// userDefaultGroup: "",
// defaultDepartment: "",
// defaultPosition: "",
// singleCharge: "",
// firstDayOfWeek: "",
// hourPerShift: "",
// cnBillingFrequency: "",
// billingDepartmentCode: "",
// basePriceList: "",
// nonContainerServiceOrderAutoApprovalDeptCode: "",
// ediMAESchedulerOnOff: "",
// ediSchedulerOnOff: "",
// logo: null,
// companyDisplayName: "",
// });
// };
// return (
// <div
// style={{
// marginTop: "10rem",
// marginBottom: "2rem",
// boxSizing: "border-box",
// }}
// >
// {loading ? (
// <Spinner />
// ) : (
// <Container
// className="system_parameter mt-5 p-4 bg-light shadow-sm rounded"
// >
// <h2
// className="title_main text-center mb-4"
// style={{ color: "#0E6591", fontWeight: "bold" }}
// >
// System Parameter Settings
// </h2>
// <Form onSubmit={handleSubmit}>
// <Row className=" mb-3">
// <Col xs={6}>
// <h6 className="heading_main text-secondary">Setup Code</h6>
// </Col>
// <Col xs={6}>
// <h6 className="heading_main text-secondary">Value</h6>
// </Col>
// </Row>
// {Object.keys(formData).map((key, index) =>
// key !== "upload_Logo" ? (
// <Row className="mb-3" key={index}>
// <Col xs={6} className="d-flex align-items-center">
// <Form.Label className="mb-0">
// {key
// .split(/(?=[A-Z])/)
// .join(" ")
// .replace(/\b\w/g, (l) => l.toUpperCase())}
// </Form.Label>
// </Col>
// <Col xs={6}>
// <Form.Control
// className="p-2 custom-hover-border"
// style={{ borderColor: "#ced4da" }}
// type="text"
// name={key}
// value={formData[key]}
// onChange={handleInputChange}
// />
// </Col>
// </Row>
// ) : (
// <Row className="mb-3" key={index}>
// <Col xs={6} className="d-flex align-items-center">
// <Form.Label className="mb-0">Upload Logo</Form.Label>
// </Col>
// <Col xs={6}>
// <Form.Control
// className="p-2 "
// style={{ borderColor: "#ced4da" }}
// type="file"
// onChange={handleFileChange}
// />
// </Col>
// </Row>
// )
// )}
// <div className="d-flex justify-content-end mt-4">
// <Button
// variant="primary"
// type="submit"
// className="me-2 px-4 py-2 custom_button"
// >
// Save
// </Button>
// <Button
// variant="outline"
// onClick={handleClear}
// className="px-4 py-2 custom_button"
// >
// Clear
// </Button>
// </div>
// </Form>
// </Container>
// )}
// </div>
// );
// };
// export default SystemParameterForm;
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Button, Form, Container, Row, Col } from "react-bootstrap"; import { Button, Form, Container, Row, Col } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css"; import "bootstrap/dist/css/bootstrap.min.css";
import "../Dashboard/CSS/CSS/CommonStyle.css"; import "../Dashboard/CSS/CSS/CommonStyle.css";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import Spinner from "../../UIComponants/Spinner"; import Spinner from "../../UIComponants/Spinner";
import {getSysParameter,addSysParameter} from "../../APIServices/SystemparameterApi"; import { getSysParameter, addSysParameter } from "../../APIServices/SystemparameterApi";
import { useSystemParameters } from "../../context/SystemParameterContext";
const SystemParameterForm = () => { const SystemParameterForm = () => {
const { systemParameters, loading: contextLoading } = useSystemParameters();
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
schedulerTime: "", schedulerTime: "",
leaseTaxCode: "", leaseTaxCode: "",
@ -181,14 +396,16 @@ const SystemParameterForm = () => {
upload_Logo: null, upload_Logo: null,
company_Display_Name: "", company_Display_Name: "",
}); });
const [loading, setLoading] = useState(true);
useEffect(() => { useEffect(() => {
// Simulate loading data if (systemParameters) {
setTimeout(() => { setFormData((prevForm) => ({
setLoading(false); ...prevForm,
}, 3000); // Simulated 3 seconds loading ...systemParameters,
}, []); }));
}
}, [systemParameters]);
const handleInputChange = (event) => { const handleInputChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
setFormData((prevState) => ({ setFormData((prevState) => ({
@ -200,62 +417,52 @@ const SystemParameterForm = () => {
const handleFileChange = (event) => { const handleFileChange = (event) => {
setFormData((prevState) => ({ setFormData((prevState) => ({
...prevState, ...prevState,
logo: event.target.files[0], upload_Logo: event.target.files[0],
})); }));
}; };
// const handleSubmit = (event) => {
// event.preventDefault();
// toast.success("Form submitted successfully!");
// // alert("Form submitted successfully!");
// console.log("Form Data:", formData);
// };
const handleSubmit = async (event) => { const handleSubmit = async (event) => {
event.preventDefault(); event.preventDefault();
try { try {
console.log("Form Data:", formData); console.log("Form Data:", formData);
const sysParamData = await addSysParameter(formData); const sysParamData = await addSysParameter(formData);
console.log("API Response:", sysParamData); console.log("API Response:", sysParamData);
toast.success("Form submitted successfully!");
toast.success("Form submitted successfully!");
} catch (error) { } catch (error) {
console.error("Error:", error.response ? error.response.data : error.message); console.error("Error:", error.response ? error.response.data : error.message);
toast.error("Failed to submit the form. Please try again."); toast.error("Failed to submit the form. Please try again.");
} }
}; };
const handleClear = () => { const handleClear = () => {
setFormData({ setFormData({
schedulerTimer: "", schedulerTime: "",
leaseTaxCode: "", leaseTaxCode: "",
vesselConfirmationProcessLimit: "", vesselConfProcessLimit: "",
rowToDisplay: "", rowToDisplay: "",
linkToDisplay: "", linkToDisplay: "",
rowToAdd: "", rowToAdd: "",
lovRowToDisplay: "", lovRowToDisplay: "",
lovLinkToDisplay: "", lovLinkToDisplay: "",
oldServerName: "", oidserverName: "",
oldBase: "", oidBase: "",
oldAdminUser: "", oidAdminUser: "",
oldServerPort: "", oidServerPort: "",
userDefaultGroup: "", userDefaultGroup: "",
defaultDepartment: "", defaultDepartment: "",
defaultPosition: "", defaultPosition: "",
singleCharge: "", singleCharge: "",
firstDayOfWeek: "", firstDayOftheWeek: "",
hourPerShift: "", hourPerShift: "",
cnBillingFrequency: "", cnBillingFrequency: "",
billingDepartmentCode: "", billingDepartmentCode: "",
basePriceList: "", basePriceList: "",
nonContainerServiceOrderAutoApprovalDeptCode: "", nonContainerServiceOrder: "",
ediMAESchedulerOnOff: "", ediMaeSchedulerONOFF: "",
ediSchedulerOnOff: "", ediSchedulerONOFF: "",
logo: null, upload_Logo: null,
companyDisplayName: "", company_Display_Name: "",
}); });
}; };
@ -267,13 +474,10 @@ const SystemParameterForm = () => {
boxSizing: "border-box", boxSizing: "border-box",
}} }}
> >
{loading ? ( {contextLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
<Container <Container className="system_parameter mt-5 p-4 bg-light shadow-sm rounded">
className="system_parameter mt-5 p-4 bg-light shadow-sm rounded"
>
<h2 <h2
className="title_main text-center mb-4" className="title_main text-center mb-4"
style={{ color: "#0E6591", fontWeight: "bold" }} style={{ color: "#0E6591", fontWeight: "bold" }}
@ -281,7 +485,7 @@ const SystemParameterForm = () => {
System Parameter Settings System Parameter Settings
</h2> </h2>
<Form onSubmit={handleSubmit}> <Form onSubmit={handleSubmit}>
<Row className=" mb-3"> <Row className="mb-3">
<Col xs={6}> <Col xs={6}>
<h6 className="heading_main text-secondary">Setup Code</h6> <h6 className="heading_main text-secondary">Setup Code</h6>
</Col> </Col>
@ -303,7 +507,7 @@ const SystemParameterForm = () => {
</Col> </Col>
<Col xs={6}> <Col xs={6}>
<Form.Control <Form.Control
className="p-2 custom-hover-border" className="p-2 custom-hover-border"
style={{ borderColor: "#ced4da" }} style={{ borderColor: "#ced4da" }}
type="text" type="text"
name={key} name={key}
@ -319,7 +523,7 @@ const SystemParameterForm = () => {
</Col> </Col>
<Col xs={6}> <Col xs={6}>
<Form.Control <Form.Control
className="p-2 " className="p-2"
style={{ borderColor: "#ced4da" }} style={{ borderColor: "#ced4da" }}
type="file" type="file"
onChange={handleFileChange} onChange={handleFileChange}

View File

@ -1,22 +1,23 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Button, Dropdown,Modal, Form ,Row,Col,InputGroup,FormControl} from "react-bootstrap"; import { Button, Dropdown, Modal, Form, Row, Col, InputGroup, FormControl, Card } from "react-bootstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEdit, faTrashAlt, faPlus,faBars,faTimes } from "@fortawesome/free-solid-svg-icons"; import { faEdit, faTrashAlt, faPlus, faBars, faTimes } from "@fortawesome/free-solid-svg-icons";
import "bootstrap/dist/css/bootstrap.min.css"; import "bootstrap/dist/css/bootstrap.min.css";
import "../Dashboard/CSS/CSS/CommonStyle.css";
import { Table, Pagination, PaginationItem, PaginationLink } from "reactstrap"; import { Table, Pagination, PaginationItem, PaginationLink } from "reactstrap";
import { FaSearch, FaTimes } from "react-icons/fa"; import { FaSearch } from "react-icons/fa";
import { BsJournals } from "react-icons/bs"; import { BsJournals } from "react-icons/bs";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import Spinner from '../../UIComponants/Spinner'; import Spinner from '../../UIComponants/Spinner';
import * as tokenRegistryAPI from './tokenregistryapi';
function TOKENRegistry() { function TOKENRegistry() {
const initialTokens = JSON.parse(localStorage.getItem("tokens")) || []; const [tokens, setTokens] = useState([]);
const [tokens, setTokens] = useState(initialTokens);
const [showAddEditModal, setShowAddEditModal] = useState(false); const [showAddEditModal, setShowAddEditModal] = useState(false);
const [showGenerateTokenModal, setShowGenerateTokenModal] = useState(false);
const [newTokenName, setNewTokenName] = useState("");
const [generatedToken, setGeneratedToken] = useState("");
const [currentToken, setCurrentToken] = useState({ const [currentToken, setCurrentToken] = useState({
tokenId: "", id: "",
tokenName: "", tokenName: "",
tokenValue: "", tokenValue: "",
isActive: true isActive: true
@ -25,50 +26,49 @@ function TOKENRegistry() {
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [recordsPerPage, setRecordsPerPage] = useState(10); const [recordsPerPage, setRecordsPerPage] = useState(10);
const [visibleColumns, setVisibleColumns] = useState({ // Add to your state:
tokenId: true, const [visibleColumns, setVisibleColumns] = useState({
tokenName: true, id: true,
tokenValue: true, tokenName: true,
isActive: true, tokenValue: true,
actions: true scopes: true,
}); isActive: true,
actions: true
});
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [selectedScopes, setSelectedScopes] = useState([]);
const [availableScopes] = useState([
{ value: 'read', label: 'Read Access' },
{ value: 'write', label: 'Write Access' },
{ value: 'delete', label: 'Delete Access' },
{ value: 'admin', label: 'Admin Access' },
]);
useEffect(() => { useEffect(() => {
const apiUrl = `${process.env.REACT_APP_API_URL}apiregistery/getall`;
const token = localStorage.getItem("authToken");
const fetchTokens = async () => {
try {
const response = await fetch(apiUrl, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setTokens(data);
localStorage.setItem("tokens", JSON.stringify(data)); // Store tokens in local storage
} catch (error) {
console.error("Error fetching tokens:", error);
}
};
fetchTokens(); fetchTokens();
}, []); }, []);
useEffect(() => { const fetchTokens = async () => {
// Simulate loading data setLoading(true);
setTimeout(() => { try {
setLoading(false); const data = await tokenRegistryAPI.fetchAllTokens();
}, 3000); // Simulated 3 seconds loading setTokens(data);
}, []); } catch (error) {
handleApiError(error, "fetch tokens");
} finally {
setLoading(false);
}
};
const handleApiError = (error, action) => {
if (error.message === 'Unauthorized') {
toast.error("Your session has expired. Please log in again.");
} else {
toast.error(`Failed to ${action}`);
console.error(`Error ${action}:`, error);
}
};
const toggleColumn = (column) => { const toggleColumn = (column) => {
setVisibleColumns(prev => ({ setVisibleColumns(prev => ({
@ -87,10 +87,14 @@ useEffect(() => {
const handleSearch = (query) => { const handleSearch = (query) => {
setSearchQuery(query); setSearchQuery(query);
setCurrentPage(1);
}; };
const handleClose = () => { const handleClose = () => {
setShowAddEditModal(false); // Close the modal by setting the state to false setShowAddEditModal(false);
setShowGenerateTokenModal(false);
setGeneratedToken("");
setNewTokenName("");
}; };
const handleRecordsPerPageChange = (number) => { const handleRecordsPerPageChange = (number) => {
@ -98,365 +102,378 @@ useEffect(() => {
setCurrentPage(1); setCurrentPage(1);
}; };
const totalPages = Math.ceil(tokens.length / recordsPerPage); const filteredTokens = tokens.filter(
(item) =>
item.tokenName &&
item.tokenName.toLowerCase().includes(searchQuery.toLowerCase())
);
const totalPages = Math.ceil(filteredTokens.length / recordsPerPage);
const handlePageChange = (pageNumber) => { const handlePageChange = (pageNumber) => {
setCurrentPage(pageNumber); setCurrentPage(pageNumber);
}; };
const slicedTokens = tokens const slicedTokens = filteredTokens.slice(
.filter( (currentPage - 1) * recordsPerPage,
(item) => currentPage * recordsPerPage
item.tokenName && );
item.tokenName.toLowerCase().includes(searchQuery.toLowerCase())
)
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
const handleSubmit = async (event) => {
const handleSubmit = (event) => {
event.preventDefault(); event.preventDefault();
try { try {
if (isEditing) { if (isEditing) {
setTokens(tokens.map(token => await tokenRegistryAPI.updateToken(currentToken.id, currentToken);
token.tokenId === currentToken.tokenId ? currentToken : token
));
toast.success("Token updated successfully!"); toast.success("Token updated successfully!");
} else { } else {
const newTokenId = `ID${tokens.length + 1}`; await tokenRegistryAPI.createToken(currentToken);
setTokens([...tokens, { ...currentToken, tokenId: newTokenId }]);
toast.success("Token added successfully!"); toast.success("Token added successfully!");
} }
setShowAddEditModal(false); setShowAddEditModal(false);
fetchTokens();
localStorage.setItem("tokens", JSON.stringify(tokens)); // Update local storage with new tokens
} catch (error) { } catch (error) {
toast.error("There was an error while submitting the token."); handleApiError(error, isEditing ? "update token" : "add token");
console.error("Error in handleSubmit:", error); // Log the error for debugging
} }
}; };
const openModal = (token = { tokenId: "", tokenName: "", tokenValue: "", isActive: false }) => { const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false }) => {
setIsEditing(!!token.tokenId); setIsEditing(!!token.id);
setCurrentToken(token); setCurrentToken(token);
setShowAddEditModal(true); setShowAddEditModal(true);
}; };
const handleDelete = (tokenId) => { const handleDelete = async (id) => {
setTokens(tokens.filter(token => token.tokenId !== tokenId)); if (window.confirm("Are you sure you want to delete this token?")) {
localStorage.setItem("tokens", JSON.stringify(tokens.filter(token => token.tokenId !== tokenId))); // Update local storage after deletion try {
toast.success('Token deleted ...'); await tokenRegistryAPI.deleteToken(id);
toast.success('Token deleted successfully');
fetchTokens();
} catch (error) {
handleApiError(error, "delete token");
}
}
}; };
const generateNewToken = async () => {
if (!newTokenName.trim()) {
toast.error("Please enter a token name");
return;
}
try {
const data = await tokenRegistryAPI.generateToken({
name: newTokenName,
scopes: selectedScopes
});
setGeneratedToken(data.tokenValue);
toast.success("Token generated successfully!");
fetchTokens();
} catch (error) {
handleApiError(error, "generate token");
}
};
return ( return (
<div style={{marginTop:"11rem"}}> <div style={{ marginTop: "1rem" }}>
{loading ? ( {loading ? (
<Spinner/> <Spinner />
):( ) : (
<div className="container-fluid mt-5"> <div className="container-fluid mt-5">
{/* Token Generation Card */}
<div className="d-flex justify-content-between align-items-center mb-4"> <Card className="mb-4 shadow-sm">
<h1 className="title_main">Token Registry</h1> <Card.Header className="d-flex justify-content-between align-items-center">
</div> <Card.Title>Token Management</Card.Title>
<Button
variant="primary"
onClick={() => setShowGenerateTokenModal(true)}
className="custom_button"
>
Generate New Token
</Button>
</Card.Header>
<Card.Body>
<p>Manage your API tokens here. Generate new tokens or delete existing ones.</p>
</Card.Body>
</Card>
<Row className="align-items-center my-3"> <div className="d-flex justify-content-between align-items-center mb-4">
{/* Left: Search Bar */} <h1 className="title_main">Token Registry</h1>
<Col </div>
xs={12}
md={8}
lg={6}
className="d-flex justify-content-center my-3"
>
<InputGroup
className="search-bar"
style={{
borderRadius: "10px",
overflow: "hidden",
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
width: "100%",
maxWidth: "528px", // Set max-width to limit overall width
paddingRight: "-15px", // Increase padding on the right side
}}
>
<InputGroup.Text
style={{
backgroundColor: "#0E6591",
color: "#fff",
padding: "10px 15px",
}}
>
<FaSearch />
</InputGroup.Text>
<FormControl
placeholder="Search"
value={searchQuery}
onChange={(e) => handleSearch(e.target.value)}
style={{
padding: "10px",
border: "none",
paddingRight: "5px", // More space on the right side of input field
}}
/>
</InputGroup>
</Col>
{/*Add Icons */} <Row className="align-items-center my-3">
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end"> <Col xs={12} md={8} lg={6} className="d-flex justify-content-center my-3">
<> <InputGroup
{/* Add Icon */} className="search-bar"
<FontAwesomeIcon
icon={faPlus}
onClick={() => openModal(true)}
style={{
cursor: "pointer",
fontSize: "1.5rem",
color: "#747264",
marginRight: "20px",
}}
/>
<FontAwesomeIcon
icon={faBars}
style={{
cursor: "pointer",
fontSize: "1.5rem",
color: "#747264",
}}
/>
</>
</Col>
</Row>
<div className="table-responsive">
<Table striped responsive hover align="middle" className=" table-flush shadow-sm">
<thead className="custom_header">
<tr>
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
<th key={key}>{key.charAt(0).toUpperCase() + key.slice(1)}</th>
))}
</tr>
</thead>
<tbody className="tbody">
{slicedTokens.length === 0 ? (
<tr>
<td
colSpan={
Object.keys(visibleColumns).filter(
(key) => visibleColumns[key]
).length
}
className="text-center"
>
No Data Available
</td>
</tr>
) : (
slicedTokens.map((token, index) => (
<tr key={index}>
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
<td key={key}>
{key === "actions" ? (
<>
<FontAwesomeIcon
icon={faEdit}
onClick={() => openModal(token)}
className="me-2"
style={{
cursor: "pointer",
fontSize: "1rem",
color: "green",
marginRight: "15px",
}}
/>
<FontAwesomeIcon
icon={faTrashAlt}
onClick={() => handleDelete(token.tokenId)}
style={{
cursor: "pointer",
fontSize: "1rem",
color: "#dc3545",
}}
/>
</>
) : key === "isActive" ? (
<span
className="status"
style={{ style={{
color: token.isActive ? "green" : "red", borderRadius: "10px",
backgroundColor: token.isActive overflow: "hidden",
? "#d4f7d4" boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
: "#f7d4d4", width: "100%",
padding: "4px 8px", maxWidth: "528px",
borderRadius: "4px",
display: "inline-block",
}} }}
> >
{token.isActive ? "Active" : "Inactive"} <InputGroup.Text style={{ backgroundColor: "#0E6591", color: "#fff", padding: "10px 15px" }}>
</span> <FaSearch />
) : ( </InputGroup.Text>
token[key] <FormControl
)} placeholder="Search"
</td> value={searchQuery}
))} onChange={(e) => handleSearch(e.target.value)}
</tr> style={{ padding: "10px", border: "none" }}
)) />
)} </InputGroup>
</tbody> </Col>
</Table> <Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
</div> <FontAwesomeIcon
icon={faPlus}
onClick={() => openModal()}
style={{
cursor: "pointer",
fontSize: "1.5rem",
color: "#747264",
marginRight: "20px",
}}
/>
<FontAwesomeIcon
icon={faBars}
style={{
cursor: "pointer",
fontSize: "1.5rem",
color: "#747264",
}}
/>
</Col>
</Row>
{/* Manage Columns & Records Per Page */} <div className="table-responsive">
<Row className="mt-4"> <Table striped responsive hover align="middle" className="table-flush shadow-sm">
<Col md={6} className="d-flex justify-content-start"> <thead className="custom_header">
<Dropdown> <tr>
<Dropdown.Toggle {Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
variant="outline-primary" <th key={key}>{key.charAt(0).toUpperCase() + key.slice(1)}</th>
className="custom_manage_column_button" ))}
> </tr>
Manage Columns </thead>
</Dropdown.Toggle> <tbody className="tbody">
<Dropdown.Menu> {slicedTokens.length === 0 ? (
{Object.keys(visibleColumns).map((column) => ( <tr>
<Dropdown.Item <td
key={column} colSpan={Object.keys(visibleColumns).filter(key => visibleColumns[key]).length}
onClick={() => toggleColumn(column)} className="text-center"
>
No Data Available
</td>
</tr>
) : (
slicedTokens.map((token, index) => (
<tr key={index}>
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
<td key={key}>
{key === "actions" ? (
<>
<FontAwesomeIcon
icon={faEdit}
onClick={() => openModal(token)}
className="me-2"
style={{
cursor: "pointer",
fontSize: "1rem",
color: "green",
marginRight: "15px",
}}
/>
<FontAwesomeIcon
icon={faTrashAlt}
onClick={() => handleDelete(token.id)}
style={{
cursor: "pointer",
fontSize: "1rem",
color: "#dc3545",
}}
/>
</>
) : key === "isActive" ? (
<span
className="status"
style={{
color: token.isActive ? "green" : "red",
backgroundColor: token.isActive ? "#d4f7d4" : "#f7d4d4",
padding: "4px 8px",
borderRadius: "4px",
display: "inline-block",
}}
>
{token.isActive ? "Active" : "Inactive"}
</span>
) : (
token[key]
)}
</td>
))}
</tr>
))
)}
</tbody>
</Table>
</div>
{/* Manage Columns & Records Per Page */}
<Row className="mt-4">
<Col md={6} className="d-flex justify-content-start">
<Dropdown>
<Dropdown.Toggle variant="outline-primary" className="custom_manage_column_button">
Manage Columns
</Dropdown.Toggle>
<Dropdown.Menu>
{Object.keys(visibleColumns).map((column) => (
<Dropdown.Item key={column} onClick={() => toggleColumn(column)}>
<Form.Check
type="checkbox"
label={column.charAt(0).toUpperCase() + column.slice(1).toLowerCase()}
checked={visibleColumns[column]}
readOnly
className="custom-checkbox"
/>
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</Col>
<Col md={6} className="d-flex justify-content-end">
<Dropdown>
<Dropdown.Toggle
variant="outline-primary"
className="custom_manage_column_button px-4 py-2 border-2 rounded-3 shadow-sm"
> >
<Form.Check <BsJournals />
type="checkbox" </Dropdown.Toggle>
label={ <Dropdown.Menu className="border-0 rounded-3 shadow-lg" align="end">
column.charAt(0).toUpperCase() + {[1, 5, 10, 20, 50].map((number) => (
column.slice(1).toLowerCase() <Dropdown.Item
} key={number}
checked={visibleColumns[column]} onClick={() => handleRecordsPerPageChange(number)}
readOnly className="text-dark d-flex justify-content-between align-items-center"
className="custom-checkbox" >
/> <span>{number}</span>
</Dropdown.Item> <i
))} className="fa fa-check-circle"
</Dropdown.Menu> style={{ display: recordsPerPage === number ? "inline" : "none" }}
</Dropdown> />
</Col> </Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</Col>
</Row>
<Col md={6} className="d-flex justify-content-end"> <Pagination className="pagination">
<Dropdown> <PaginationItem disabled={currentPage === 1}>
<Dropdown.Toggle <PaginationLink previous onClick={() => handlePageChange(currentPage - 1)} />
variant="outline-primary" </PaginationItem>
className="custom_manage_column_button px-4 py-2 border-2 rounded-3 shadow-sm" {[...Array(totalPages)].map((_, index) => (
id="dropdown-custom-components" <PaginationItem key={index} active={index + 1 === currentPage}>
> <PaginationLink onClick={() => handlePageChange(index + 1)} style={{ color: "#0b6592" }}>
<BsJournals /> {index + 1}
</Dropdown.Toggle> </PaginationLink>
<Dropdown.Menu className="border-0 rounded-3 shadow-lg" align="end"> </PaginationItem>
{[1, 5, 10, 20, 50].map((number) => ( ))}
<Dropdown.Item <PaginationItem disabled={currentPage === totalPages}>
key={number} <PaginationLink next onClick={() => handlePageChange(currentPage + 1)} />
onClick={() => handleRecordsPerPageChange(number)} </PaginationItem>
className="text-dark d-flex justify-content-between align-items-center" </Pagination>
>
<span>{number}</span>
<i
className="fa fa-check-circle"
style={{
display: recordsPerPage === number ? "inline" : "none",
}}
/>
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</Col>
</Row>
<Pagination className="pagination"> {/* Add/Edit Token Modal */}
<PaginationItem disabled={currentPage === 1}> <Modal show={showGenerateTokenModal} onHide={handleClose}>
<PaginationLink <Modal.Header>
previous <Modal.Title>Generate New Token</Modal.Title>
onClick={() => handlePageChange(currentPage - 1)} <FontAwesomeIcon
icon={faTimes}
size="lg"
onClick={handleClose}
style={{
position: "absolute",
top: "25px",
right: "25px",
cursor: "pointer",
}}
/>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formNewTokenName" className="mb-3">
<Form.Label>Token Name</Form.Label>
<Form.Control
type="text"
value={newTokenName}
onChange={(e) => setNewTokenName(e.target.value)}
required
className="custom-hover-border"
placeholder="Enter a name for the new token"
/>
</Form.Group>
<Form.Group controlId="formTokenScopes" className="mb-3">
<Form.Label>Token Scopes</Form.Label>
<Form.Select
multiple
value={selectedScopes}
onChange={(e) => {
const options = [...e.target.options];
const selectedValues = options
.filter(option => option.selected)
.map(option => option.value);
setSelectedScopes(selectedValues);
}}
className="custom-hover-border"
style={{ height: 'auto' }}
>
{availableScopes.map(scope => (
<option key={scope.value} value={scope.value}>
{scope.label}
</option>
))}
</Form.Select>
<Form.Text className="text-muted">
Select the permissions this token should have (hold Ctrl/Cmd to select multiple)
</Form.Text>
</Form.Group>
{generatedToken && (
<Form.Group controlId="formGeneratedToken" className="mb-3">
<Form.Label>Generated Token</Form.Label>
<Form.Control
as="textarea"
rows={3}
value={generatedToken}
readOnly
className="custom-hover-border"
/> />
</PaginationItem> <Form.Text className="text-muted">
{[...Array(totalPages)].map((_, index) => ( Copy this token and store it securely. You won't be able to see it again.
<PaginationItem key={index} active={index + 1 === currentPage}> </Form.Text>
<PaginationLink </Form.Group>
onClick={() => handlePageChange(index + 1)} )}
style={{ color: "#0b6592" }}
> <Modal.Footer>
{index + 1} <Button variant="secondary" onClick={handleClose}>
</PaginationLink> Close
</PaginationItem> </Button>
))} <Button
<PaginationItem disabled={currentPage === totalPages}> variant="primary"
<PaginationLink onClick={generateNewToken}
next disabled={!newTokenName.trim()}
onClick={() => handlePageChange(currentPage + 1)} >
/> Generate Token
</PaginationItem> </Button>
</Pagination> </Modal.Footer>
</Form>
</Modal.Body>
</Modal>
<Modal show={showAddEditModal} onHide={() => setShowAddEditModal(false)}> </div>
<Modal.Header >
<Modal.Title>{isEditing ? "Edit Token" : "Add Token"}</Modal.Title>
<FontAwesomeIcon
icon={faTimes}
size="lg"
onClick={handleClose}
style={{
position: "absolute",
top: "25px",
right: "25px",
cursor: "pointer",
}}
/>
</Modal.Header>
<Modal.Body>
<Form onSubmit={handleSubmit}>
<Form.Group controlId="formTokenName">
<Form.Label>Token Name</Form.Label>
<Form.Control
type="text"
name="tokenName"
value={currentToken.tokenName}
onChange={handleInputChange}
required
className="custom-hover-border"
/>
</Form.Group>
<Form.Group controlId="formTokenValue">
<Form.Label>Token Value</Form.Label>
<Form.Control
type="text"
name="tokenValue"
value={currentToken.tokenValue}
onChange={handleInputChange}
required
className="custom-hover-border"
/>
</Form.Group>
<Form.Group controlId="formActive">
<Form.Check
type="checkbox"
label="Active?"
name="isActive"
checked={currentToken.isActive}
onChange={handleInputChange}
className="custom-checkbox"
/>
</Form.Group>
<Modal.Footer>
<Button variant="primary" className="custom_button px-4" onClick={() => setShowAddEditModal(false)}>Close</Button>
<Button variant="primary" className="custom_button px-4" type="submit">{isEditing ? "Update Token" : "Add Token"}</Button>
</Modal.Footer>
</Form>
</Modal.Body>
</Modal>
</div>
)} )}
</div> </div>
); );
} }
export default TOKENRegistry; export default TOKENRegistry;

View File

@ -313,7 +313,7 @@ export function UserGroupMaintenance() {
) )
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage); .slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
return ( return (
<div style={{ marginTop: "11rem" }}> <div style={{ marginTop: "7rem" }}>
{loading ? ( {loading ? (
<Spinner /> <Spinner />
) : ( ) : (
@ -366,11 +366,11 @@ export function UserGroupMaintenance() {
{/*Add Icons */} {/*Add Icons */}
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end"> <Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
<> <>
<OverlayTrigger {/* <OverlayTrigger
placement="bottom" placement="bottom"
overlay={<Tooltip>Add Group</Tooltip>} overlay={<Tooltip>Add Group</Tooltip>}
> > */}
<FontAwesomeIcon {/* <FontAwesomeIcon
icon={faPlus} icon={faPlus}
onClick={() => handleAddItem(true)} onClick={() => handleAddItem(true)}
style={{ style={{
@ -379,8 +379,8 @@ export function UserGroupMaintenance() {
color: "#747264", color: "#747264",
marginRight: "20px", marginRight: "20px",
}} }}
/> /> */}
</OverlayTrigger> {/* </OverlayTrigger> */}
<OverlayTrigger <OverlayTrigger
placement="bottom" placement="bottom"
overlay={<Tooltip>Download template</Tooltip>} overlay={<Tooltip>Download template</Tooltip>}
@ -426,7 +426,7 @@ export function UserGroupMaintenance() {
}} }}
/> />
</OverlayTrigger> </OverlayTrigger>
<OverlayTrigger {/* <OverlayTrigger
placement="bottom" placement="bottom"
overlay={<Tooltip>Menu</Tooltip>} overlay={<Tooltip>Menu</Tooltip>}
> >
@ -438,7 +438,7 @@ export function UserGroupMaintenance() {
color: "#747264", color: "#747264",
}} }}
/> />
</OverlayTrigger> </OverlayTrigger> */}
{/* Add Icon */} {/* Add Icon */}
</> </>
</Col> </Col>

View File

@ -579,7 +579,7 @@ function UserMaintenanceView() {
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage); .slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
return ( return (
<div style={{marginTop:"8rem"}}> <div style={{marginTop:"7rem"}}>
{loading ? ( {loading ? (
<Spinner/> <Spinner/>
):( ):(
@ -634,7 +634,7 @@ function UserMaintenanceView() {
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end"> <Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
<> <>
{/* Add Icon */} {/* Add Icon */}
<OverlayTrigger placement="bottom" overlay={<Tooltip>Add Items</Tooltip>}> {/* <OverlayTrigger placement="bottom" overlay={<Tooltip>Add Items</Tooltip>}>
<FontAwesomeIcon <FontAwesomeIcon
icon={faPlus} icon={faPlus}
onClick={() => handleAddItem(true)} onClick={() => handleAddItem(true)}
@ -649,7 +649,7 @@ function UserMaintenanceView() {
title="Add Item" title="Add Item"
/> />
</OverlayTrigger> </OverlayTrigger>
*/}
<OverlayTrigger placement="bottom" overlay={<Tooltip>Download template</Tooltip>}> <OverlayTrigger placement="bottom" overlay={<Tooltip>Download template</Tooltip>}>
<FontAwesomeIcon <FontAwesomeIcon
icon={faDownload} icon={faDownload}
@ -687,7 +687,7 @@ function UserMaintenanceView() {
/> />
</OverlayTrigger> </OverlayTrigger>
<OverlayTrigger placement="bottom" overlay={<Tooltip>Menu Items</Tooltip>}> {/* <OverlayTrigger placement="bottom" overlay={<Tooltip>Menu Items</Tooltip>}>
<FontAwesomeIcon <FontAwesomeIcon
icon={faBars} icon={faBars}
style={{ style={{
@ -697,7 +697,7 @@ function UserMaintenanceView() {
}} }}
/> />
</OverlayTrigger> </OverlayTrigger>
*/}
</> </>
</Col> </Col>
</Row> </Row>

View File

@ -7,6 +7,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrash, faGripLines, faPen } from '@fortawesome/free-solid-svg-icons'; import { faTrash, faGripLines, faPen } from '@fortawesome/free-solid-svg-icons';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import DashboardBuilderService from "../../../../APIServices/DashboardBuilderService"; import DashboardBuilderService from "../../../../APIServices/DashboardBuilderService";
import TextField from '@mui/material/TextField';
import FormControlLabel from '@mui/material/FormControlLabel';
// Import chart components // Import chart components
import LineChartComponent from '../gadgets/line-chart/LineChart'; import LineChartComponent from '../gadgets/line-chart/LineChart';
@ -248,6 +250,7 @@ const EditNewDash = () => {
// Edit widget // Edit widget
const editWidget = (widget) => { const editWidget = (widget) => {
console.log("Opening edit modal for:", widget);
setCurrentEditWidget(widget); setCurrentEditWidget(widget);
setEditModalOpen(true); setEditModalOpen(true);
}; };
@ -420,6 +423,7 @@ const EditNewDash = () => {
> >
<ResponsiveGridLayout <ResponsiveGridLayout
className="layout" className="layout"
draggableCancel=".MuiButton-root, .MuiIconButton-root, button, [role='button']"
layouts={{ layouts={{
lg: dashboardWidgets.map(widget => ({ lg: dashboardWidgets.map(widget => ({
i: widget.i, i: widget.i,
@ -458,17 +462,23 @@ const EditNewDash = () => {
{widget.name} {widget.name}
</Typography> </Typography>
<Box> <Box>
<Button <Button
size="small" size="small"
onClick={() => editWidget(widget)} onClick={(e) => {
sx={{ minWidth: 'auto', padding: '4px' }} e.stopPropagation();
> editWidget(widget);
<FontAwesomeIcon icon={faPen} /> }}
</Button> >
<FontAwesomeIcon icon={faPen} />
</Button>
<Button <Button
size="small" size="small"
color="error" color="error"
onClick={() => removeWidget(widget.i)} onClick={() => {
console.log("Edit button clicked for widget:", widget);
removeWidget(widget.i)}
}
sx={{ minWidth: 'auto', padding: '4px', ml: 1 }} sx={{ minWidth: 'auto', padding: '4px', ml: 1 }}
> >
<FontAwesomeIcon icon={faTrash} /> <FontAwesomeIcon icon={faTrash} />
@ -512,93 +522,69 @@ const EditNewDash = () => {
{/* Edit widget dialog */} {/* Edit widget dialog */}
<Dialog open={editModalOpen} onClose={() => setEditModalOpen(false)} maxWidth="sm" fullWidth> <Dialog open={editModalOpen} onClose={() => setEditModalOpen(false)} maxWidth="sm" fullWidth>
<DialogTitle>Edit {currentEditWidget.name}</DialogTitle> <DialogTitle>Edit {currentEditWidget?.name}</DialogTitle>
<DialogContent sx={{ paddingTop: 2 }}> <DialogContent dividers>
<FormControl fullWidth sx={{ marginBottom: 2 }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>Chart Title</Typography> <TextField
<Input label="Chart Title"
value={currentEditWidget.chartTitle || ''} fullWidth
onChange={(e) => setCurrentEditWidget({ value={currentEditWidget?.chartTitle || ''}
...currentEditWidget, onChange={(e) =>
chartTitle: e.target.value setCurrentEditWidget((prev) => ({ ...prev, chartTitle: e.target.value }))
})} }
placeholder="Enter chart title" />
fullWidth <TextField
label="X Axis Label"
fullWidth
value={currentEditWidget?.xAxis || ''}
onChange={(e) =>
setCurrentEditWidget((prev) => ({ ...prev, xAxis: e.target.value }))
}
/>
<TextField
label="Y Axis Label"
fullWidth
value={currentEditWidget?.yAxis || ''}
onChange={(e) =>
setCurrentEditWidget((prev) => ({ ...prev, yAxis: e.target.value }))
}
/>
<FormControl>
<FormControlLabel
control={
<Checkbox
checked={currentEditWidget?.showLegend ?? true}
onChange={(e) =>
setCurrentEditWidget((prev) => ({ ...prev, showLegend: e.target.checked }))
}
/> />
</FormControl> }
label="Show Legend"
{currentEditWidget.name !== 'Grid View' && currentEditWidget.name !== 'Todo Chart' && ( />
<> <FormControlLabel
<Box sx={{ display: 'flex', gap: 2, marginBottom: 2 }}> control={
<FormControl sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}> <Checkbox
<Checkbox checked={currentEditWidget?.showLabel ?? true}
checked={currentEditWidget.showLegend || false} onChange={(e) =>
onChange={(e) => setCurrentEditWidget({ setCurrentEditWidget((prev) => ({ ...prev, showLabel: e.target.checked }))
...currentEditWidget, }
showLegend: e.target.checked />
})} }
/> label="Show Labels"
<Typography>Show Legend</Typography> />
</FormControl> </FormControl>
<FormControl sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<Checkbox
checked={currentEditWidget.showLabel || false}
onChange={(e) => setCurrentEditWidget({
...currentEditWidget,
showLabel: e.target.checked
})}
/>
<Typography>Show Labels</Typography>
</FormControl>
</Box>
</>
)}
<FormControl fullWidth sx={{ marginBottom: 2 }}>
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>X-Axis</Typography>
<Select
value={currentEditWidget.xAxis || ''}
onChange={(e) => setCurrentEditWidget({
...currentEditWidget,
xAxis: e.target.value
})}
displayEmpty
>
<MenuItem value="" disabled>Select X-Axis</MenuItem>
{columnData.map((col, index) => (
<MenuItem key={index} value={col}>{col}</MenuItem>
))}
</Select>
</FormControl>
<FormControl fullWidth sx={{ marginBottom: 2 }}>
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>Y-Axis</Typography>
<Select
value={currentEditWidget.yAxis || ''}
onChange={(e) => setCurrentEditWidget({
...currentEditWidget,
yAxis: e.target.value
})}
displayEmpty
>
<MenuItem value="" disabled>Select Y-Axis</MenuItem>
{columnData.map((col, index) => (
<MenuItem key={index} value={col}>{col}</MenuItem>
))}
</Select>
</FormControl>
</DialogContent>
<DialogActions sx={{ padding: 2 }}>
<Button onClick={() => setEditModalOpen(false)} color="inherit">
Cancel
</Button>
<Button onClick={saveWidgetChanges} variant="contained" color="primary">
Save Changes
</Button>
</DialogActions>
</Dialog>
</Box> </Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setEditModalOpen(false)} color="secondary">
Cancel
</Button>
<Button onClick={saveWidgetChanges} variant="contained" color="primary">
Save Changes
</Button>
</DialogActions>
</Dialog>
</Box>
); );
}; };

View File

@ -0,0 +1,299 @@
import React, { useState, useEffect } from 'react';
import {
Table,
Button,
Modal,
Form,
Input,
InputNumber,
Dropdown,
Alert,
message,
Card,
Descriptions
} from 'antd';
import {
EllipsisOutlined,
PlusOutlined,
EditOutlined,
DeleteOutlined
} from '@ant-design/icons';
import SequenceGeneratorAPI from './sequencegeneratorapi';
const SequenceGenerator = () => {
const [sequences, setSequences] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [visible, setVisible] = useState(false);
const [editingId, setEditingId] = useState(null);
const [currentSequence, setCurrentSequence] = useState(null);
const [form] = Form.useForm();
useEffect(() => {
fetchSequences();
}, []);
const fetchSequences = async () => {
setLoading(true);
try {
const data = await SequenceGeneratorAPI.getAll();
setSequences(data);
} catch (err) {
setError(err.response?.data?.message || 'Failed to fetch sequences');
} finally {
setLoading(false);
}
};
const handleCreate = () => {
form.resetFields();
setCurrentSequence(null);
setEditingId(null);
setVisible(true);
};
const handleEdit = (record) => {
form.setFieldsValue(record);
setCurrentSequence(record);
setEditingId(record.id);
setVisible(true);
};
const handleDelete = async (id) => {
Modal.confirm({
title: 'Confirm Delete',
content: 'Are you sure you want to delete this sequence?',
okText: 'Delete',
okType: 'danger',
cancelText: 'Cancel',
onOk: async () => {
try {
await SequenceGeneratorAPI.delete(id);
message.success('Sequence deleted successfully');
fetchSequences();
} catch (err) {
message.error(err.response?.data?.message || 'Failed to delete sequence');
}
}
});
};
const handleSubmit = async () => {
try {
const values = await form.validateFields();
if (editingId) {
await SequenceGeneratorAPI.update(editingId, values);
message.success('Sequence updated successfully');
} else {
await SequenceGeneratorAPI.create(values);
message.success('Sequence created successfully');
}
setVisible(false);
fetchSequences();
} catch (err) {
message.error(err.response?.data?.message || 'Operation failed');
}
};
const columns = [
{
title: 'Actions',
key: 'actions',
width: 100,
render: (_, record) => (
<Dropdown
menu={{
items: [
{
key: 'edit',
label: 'Edit',
icon: <EditOutlined />,
onClick: () => handleEdit(record)
},
{
key: 'delete',
label: 'Delete',
icon: <DeleteOutlined />,
danger: true,
onClick: () => handleDelete(record.id)
}
]
}}
trigger={['click']}
>
<Button type="text" icon={<EllipsisOutlined />} />
</Dropdown>
),
},
{
title: 'Name',
dataIndex: 'sequence_name',
key: 'sequence_name',
},
{
title: 'Sequence Code',
dataIndex: 'sequence_code',
key: 'sequence_code',
},
{
title: 'Current No',
dataIndex: 'current_no',
key: 'current_no',
},
{
title: 'Demonstration',
dataIndex: 'demonstration',
key: 'demonstration',
}
];
return (
<div className="sequence-generator-container">
{error && (
<Alert
message="Error"
description={error}
type="error"
showIcon
closable
onClose={() => setError(null)}
style={{ marginBottom: 16 }}
/>
)}
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
<h2>Document Sequence</h2>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleCreate}
>
Add Sequence
</Button>
</div>
<Table
columns={columns}
dataSource={sequences}
rowKey="id"
loading={loading}
pagination={{
pageSize: 10,
showSizeChanger: true,
showTotal: (total) => `Total ${total} sequences`,
}}
/>
<Modal
title={<span style={{ fontWeight: 'bold' }}>Update Sequence Generator</span>}
open={visible}
onOk={handleSubmit}
onCancel={() => setVisible(false)}
confirmLoading={loading}
width={700}
>
{currentSequence && (
<div style={{
marginLeft: 20,
marginBottom: 24,
border: '1px solid #d9d9d9',
borderRadius: 4,
padding: 16,
backgroundColor: '#fafafa'
}}>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tbody>
<tr>
<td style={{
padding: '8px 16px',
borderBottom: '1px solid #e8e8e8',
fontWeight: 'bold',
width: '30%'
}}>Sequence ID</td>
<td style={{
padding: '8px 16px',
borderBottom: '1px solid #e8e8e8'
}}>{currentSequence.id}</td>
</tr>
<tr>
<td style={{
padding: '8px 16px',
fontWeight: 'bold'
}}>Demonstration</td>
<td style={{ padding: '8px 16px' }}>
<div style={{
backgroundColor: '#f5f5f5',
padding: 8,
textAlign: 'center',
borderRadius: 4,
fontWeight: 'bold'
}}>
{currentSequence.demonstration}
</div>
</td>
</tr>
</tbody>
</table>
</div>
)}
<Form form={form} layout="vertical" style={{ marginLeft: 20, marginRight: 20 }}>
<Form.Item
name="sequence_name"
label={<span style={{ fontWeight: 'bold' }}>Name*</span>}
rules={[{ required: true, message: 'Please input the sequence name!' }]}
>
<Input />
</Form.Item>
<Form.Item
name="sequence_code"
label={<span style={{ fontWeight: 'bold' }}>Sequence Code</span>}
>
<Input />
</Form.Item>
<Form.Item
name="prefix"
label={<span style={{ fontWeight: 'bold' }}>Prefix*</span>}
rules={[{ required: true, message: 'Please input the prefix!' }]}
>
<Input />
</Form.Item>
<Form.Item
name="suffix"
label={<span style={{ fontWeight: 'bold' }}>Suffix</span>}
>
<Input />
</Form.Item>
<Form.Item
name="seperator"
label={<span style={{ fontWeight: 'bold' }}>Separator</span>}
>
<Input />
</Form.Item>
<Form.Item
name="starting_no"
label={<span style={{ fontWeight: 'bold' }}>Starting No</span>}
>
<InputNumber min={1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item
name="current_no"
label={<span style={{ fontWeight: 'bold' }}>Current No</span>}
>
<InputNumber min={1} style={{ width: '100%' }} />
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default SequenceGenerator;

View File

@ -0,0 +1,80 @@
import axios from 'axios';
import { getToken } from '../../utils/tokenService.js';
const API_BASE_URL = process.env.REACT_APP_API_URL || '';
const api = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json'
}
});
// Add request interceptor to attach token
api.interceptors.request.use((config) => {
// Always get fresh token for each request
const token = getToken();
console.log('[API] Current token:', token); // Log the token
console.log('[API] Making request to:', config.url); // Log the request URL
if (token) {
config.headers.Authorization = `Bearer ${token}`;
} else {
console.warn('No authToken found for request!');
}
return config;
}, (error) => {
console.error('[API] Request error:', error);
return Promise.reject(error);
});
// ... rest of the interceptors and API methods remain the same ...
// Add response interceptor to log responses
api.interceptors.response.use((response) => {
console.log('[API] Response received:', {
status: response.status,
url: response.config.url,
data: response.data
});
return response;
}, (error) => {
console.error('[API] Response error:', {
status: error.response?.status,
url: error.config?.url,
message: error.message,
response: error.response?.data
});
return Promise.reject(error);
});
const SequenceGeneratorAPI = {
getAll: async () => {
try {
console.log('[API] Fetching all sequences'); // Additional log
const response = await api.get('/sureserve/sequence/seq');
return response.data;
} catch (error) {
console.error('[API] Error fetching sequences:', error);
throw error;
}
},
getById: async (id) => {
try {
console.log(`[API] Fetching sequence with ID: ${id}`);
const response = await api.get(`/sureserve/sequence/seq/${id}`);
return response.data;
} catch (error) {
console.error(`[API] Error fetching sequence ${id}:`, error);
throw error;
}
},
create: async (data) => api.post('/sureserve/sequence/seq', data), // ✅ Make sure this exists
update: async (id, data) => api.put(`/sureserve/sequence/seq/${id}`, data),
delete: async (id) => api.delete(`/sureserve/sequence/seq/${id}`),
};
export default SequenceGeneratorAPI;

View File

@ -0,0 +1,88 @@
// src/services/tokenRegistryAPI.js
import axios from 'axios';
import { getToken } from '../../utils/tokenService.js';
// Create axios instance with base configuration
const apiClient = axios.create({
baseURL: process.env.REACT_APP_API_URL || 'http://157.66.191.31:33730/back/',
});
// Add request interceptor to inject token
apiClient.interceptors.request.use((config) => {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (error) => {
return Promise.reject(error);
});
// Response interceptor for error handling
apiClient.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response) {
// Handle specific status codes
if (error.response.status === 401) {
// Handle unauthorized (token expired)
console.error('Authentication failed');
}
throw new Error(error.response.data.message || 'Request failed');
}
throw new Error(error.message || 'Network error');
}
);
export const fetchAllTokens = async () => {
try {
return await apiClient.get('apiregistery/getall');
} catch (error) {
console.error('Fetch tokens error:', error);
throw error;
}
};
export const generateToken = async (token_name) => {
try {
return await apiClient.post(
'apiregistery/generateToken',
new URLSearchParams({ token_name }),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);
} catch (error) {
console.error('Generate token error:', error);
throw error;
}
};
export const createToken = async (tokenData) => {
try {
return await apiClient.post('apiregistery/create', tokenData);
} catch (error) {
console.error('Create token error:', error);
throw error;
}
};
export const updateToken = async (id, tokenData) => {
try {
return await apiClient.put(`apiregistery/update/${id}`, tokenData);
} catch (error) {
console.error('Update token error:', error);
throw error;
}
};
export const deleteToken = async (id) => {
try {
return await apiClient.delete(`apiregistery/delete/${id}`);
} catch (error) {
console.error('Delete token error:', error);
throw error;
}
};

View File

@ -157,7 +157,7 @@ const Header = () => {
return ( return (
<> <>
<div <div
className="header bg-gradient-info pb-8 pt-7 pt-md-12" className="header pb-8 pt-7 pt-md-12"
style={{ marginTop: "6rem" }} style={{ marginTop: "6rem" }}
> >
{" "} {" "}

View File

@ -1,60 +1,31 @@
/*!
=========================================================
* Argon Dashboard React - v1.2.4
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-react
* Copyright 2024 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://github.com/creativetimofficial/argon-dashboard-react/blob/master/LICENSE.md)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// reactstrap components
import { Button, Container, Row, Col } from "reactstrap"; import { Button, Container, Row, Col } from "reactstrap";
const UserHeader = () => { const UserHeader = ({ user }) => {
return ( return (
<> <div
<div className="header pb-8 pt-5 pt-lg-8 d-flex align-items-center"
className="header pb-8 pt-5 pt-lg-8 d-flex align-items-center" style={{
style={{ minHeight: "600px",
minHeight: "600px", backgroundSize: "cover",
backgroundImage: backgroundPosition: "center top",
"url(" + require("../../assets/img/theme/profile-cover.jpg") + ")", }}
backgroundSize: "cover", >
backgroundPosition: "center top", {/* Mask */}
}} <span className="mask bg-gradient-default opacity-8" />
> {/* Header container */}
{/* Mask */} <Container className="d-flex align-items-center" fluid>
<span className="mask bg-gradient-default opacity-8" /> <Row>
{/* Header container */} <Col lg="7" md="10">
<Container className="d-flex align-items-center" fluid> <h1 className="display-2 text-white">
<Row> Hello {user?.firstName || "User"}
<Col lg="7" md="10"> </h1>
<h1 className="display-2 text-white">Hello Jesse</h1> <p className="text-white mt-0 mb-5">
<p className="text-white mt-0 mb-5"> Welcome back, {user?.role || "team member"}! Manage your profile and activity here.
This is your profile page. You can see the progress you've made </p>
with your work and manage your projects or assigned tasks </Col>
</p> </Row>
<Button </Container>
color="info" </div>
href="#pablo"
onClick={(e) => e.preventDefault()}
>
Edit profile
</Button>
</Col>
</Row>
</Container>
</div>
</>
); );
}; };

View File

@ -9,6 +9,17 @@
left: 0; left: 0;
z-index: 1030; z-index: 1030;
} }
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
border-radius: 0.25rem;
}
/* Container */ /* Container */
.navbar-container { .navbar-container {
@ -153,21 +164,63 @@ body {
padding-top: 60px; padding-top: 60px;
} }
/* Responsive */ @media (min-width: 992px) {
@media (max-width: 768px) { .mobile-sidebar-toggle {
.navbar-container { display: none !important;
}
.mobile-right-sidebar {
display: none !important;
}
}
@media (max-width: 992px) {
.mobile-sidebar-toggle {
display: block !important;
background: none;
border: none;
color: white;
font-size: 1.5rem;
margin-right: 1rem;
}
.mobile-right-sidebar {
display: flex;
flex-direction: column; flex-direction: column;
padding: 0.5rem; position: fixed;
top: 68px;
right: 0;
background: #e8e8e8;
padding: 2rem;
z-index: 1050;
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
height: 100vh;
width: 240px;
gap: 1rem; gap: 1rem;
transform: translateX(100%);
transition: transform 0.3s ease-in-out;
}
.mobile-right-sidebar.open {
transform: translateX(0);
}
.mobile-right-sidebar .nav-icon {
color: #000;
display: flex;
align-items: center;
font-size: 1rem;
gap: 0.5rem;
text-decoration: none;
}
.mobile-right-sidebar .nav-icon:hover {
color: #0078b9;
} }
.nav-icons { .nav-icons {
justify-content: center; display: none !important;
gap: 1rem;
} }
.search-input-group {
width: 100%; }
max-width: 300px;
}
}

View File

@ -1,19 +1,13 @@
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import { removeCurrentUser,getCurrentUser } from "../../utils/tokenService"; import { removeCurrentUser, getCurrentUser } from "../../utils/tokenService";
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faUser } from "@fortawesome/free-solid-svg-icons"; import { faUser, faBars } from "@fortawesome/free-solid-svg-icons";
import { import {
DropdownMenu, DropdownMenu,
DropdownItem, DropdownItem,
UncontrolledDropdown, UncontrolledDropdown,
DropdownToggle, DropdownToggle,
Form,
FormGroup,
InputGroupAddon,
InputGroupText,
Input,
InputGroup,
Navbar, Navbar,
Nav, Nav,
Media, Media,
@ -22,118 +16,204 @@ import "./AdminNavbar.css";
import "bootstrap-icons/font/bootstrap-icons.css"; import "bootstrap-icons/font/bootstrap-icons.css";
const AdminNavbar = ({ brandText }) => { const AdminNavbar = ({ brandText }) => {
const[currentUser,setCurrentUser]=useState(); const [submenuOpen, setSubmenuOpen] = useState(false);
const navigate = useNavigate();
const [currentUser, setCurrentUser] = useState();
const [sidebarOpen, setSidebarOpen] = useState(false);
useEffect(() => { useEffect(() => {
const user = getCurrentUser(); const user = getCurrentUser();
console.log(user);
setCurrentUser(user); setCurrentUser(user);
console.log(currentUser); if (!user) navigate("/login");
if (!user) {
navigate("/login");
}
}, []); }, []);
console.log(brandText);
const navigate = useNavigate();
const handleLogout = () => { const handleLogout = () => {
removeCurrentUser(); removeCurrentUser();
// localStorage.removeItem("authToken"); // Uncomment if needed
navigate("/login"); navigate("/login");
}; };
const toggleSidebar = () => setSidebarOpen(!sidebarOpen);
return ( return (
<Navbar className="navbar-top navbar-dark" expand="lg" id="navbar-main"> <>
<div className="navbar-container container-fluid"> <Navbar className="navbar-top navbar-dark" expand={false} id="navbar-main">
{/* Brand */}
<Link className="brand_name h4 mb-0 text-white text-uppercase" to="/"> <div className="navbar-container container-fluid">
{brandText} {/* Toggle sidebar on small screens */}
</Link> <button className="mobile-sidebar-toggle" onClick={toggleSidebar}>
<FontAwesomeIcon icon={faBars} />
</button>
{/* Navigation Icons */} <Link className="brand_name h4 mb-0 text-white text-uppercase" to="/">
<div className="nav-icons d-flex align-items-center"> {brandText}
<Link to="/admin/index" className="nav-icon">
<i className="fas fa-home" />
</Link> </Link>
<Link to="/admin/setting" className="nav-icon">
<i className="ni ni-settings-gear-65" />
</Link>
<Link to="/admin/dashboard-runner-all" className="nav-icon">
<i className="bi bi-grid" />
</Link>
<Link to="/admin/report-runner" className="nav-icon">
<i className="ni ni-chart-bar-32" />
</Link>
<Link to="/admin/user-report" className="nav-icon">
<i className="ni ni-grid" />
</Link>
</div>
{/* Search and Profile */} <div className="nav-icons d-none d-lg-flex">
<div className="nav-right d-flex align-items-center"> <Link to="/admin/index" className="nav-icon">
<Form className="navbar-search navbar-search-dark form-inline"> <i className="fas fa-home" />
{/* <FormGroup className="mb-0"> </Link>
<InputGroup className="input-group-alternative search-input-group"> <Link to="/admin/setting" className="nav-icon">
<InputGroupAddon addonType="prepend"> <i className="ni ni-settings-gear-65" />
<InputGroupText className="search-icon"> </Link>
<i className="fas fa-search" /> <Link to="/admin/dashboard-runner-all" className="nav-icon">
</InputGroupText> <i className="bi bi-grid" />
</InputGroupAddon> </Link>
<Input placeholder="Search" type="text" className="search-input" /> <Link to="/admin/report-runner" className="nav-icon">
</InputGroup> <i className="ni ni-chart-bar-32" />
</FormGroup> */} </Link>
</Form> <Link to="/admin/user-report" className="nav-icon">
<i className="ni ni-grid" />
</Link>
</div>
<Nav className="align-items-center" navbar>
<UncontrolledDropdown nav>
<DropdownToggle className="pr-0" nav> {/* Right Sidebar for larger screens */}
<Media className="align-items-center"> <div className="nav-right d-none d-lg-flex align-items-center">
<span className="avatar avatar-sm rounded-circle"> <Nav className="align-items-center" navbar>
{/* <img <UncontrolledDropdown nav>
alt="Profile" <DropdownToggle className="pr-0" nav>
src={require("../../assets/img/theme/team-4-800x800.jpg")} <Media className="align-items-center">
/> */} <span className="avatar avatar-sm rounded-circle">
<FontAwesomeIcon icon={faUser} /> <FontAwesomeIcon icon={faUser} />
</span>
<Media className="ml-2 d-none d-lg-block">
<span className="brand_name mb-0 text-sm font-weight-bold text-white-50">
{currentUser ? currentUser.fullname : "Guest"}
</span> </span>
<Media className="ml-2 d-none d-lg-block">
<span className="brand_name mb-0 text-sm font-weight-bold text-white-50">
{currentUser ? currentUser.fullname : "Guest"}
</span>
</Media>
</Media> </Media>
</Media> </DropdownToggle>
</DropdownToggle> <DropdownMenu className="dropdown-menu-arrow" right>
<DropdownMenu className="dropdown-menu-arrow" right> <DropdownItem header tag="div">
<DropdownItem className="noti-title" header tag="div">
<h6 className="text-overflow m-0">Welcome!</h6> <h6 className="text-overflow m-0">Welcome!</h6>
</DropdownItem> </DropdownItem>
<DropdownItem to="/admin/user-profile" tag={Link}> <DropdownItem to="/admin/about" tag={Link}>
<i className="fas fa-info-circle" /> {/* Font Awesome alternative */}
<span>About</span>
</DropdownItem>
<DropdownItem to="/admin/profile" tag={Link}>
<i className="ni ni-single-02" /> <i className="ni ni-single-02" />
<span>My profile</span> <span>My profile</span>
</DropdownItem> </DropdownItem>
<DropdownItem to="/admin/user-profile" tag={Link}> <DropdownItem to="/admin/dashboard-runner-all" tag={Link}>
<i className="ni ni-settings-gear-65" />
<span>Settings</span>
</DropdownItem>
<DropdownItem to="/admin/user-profile" tag={Link}>
<i className="ni ni-calendar-grid-58" /> <i className="ni ni-calendar-grid-58" />
<span>Activity</span> <span>Activity</span>
</DropdownItem> </DropdownItem>
<DropdownItem to="/admin/user-profile" tag={Link}>
<i className="ni ni-support-16" /> {/* Nested Language Dropdown */}
<span>Support</span> <div
className="dropdown-submenu"
onMouseEnter={() => setSubmenuOpen(true)}
onMouseLeave={() => setSubmenuOpen(false)}
>
<DropdownItem
className="dropdown-toggle"
toggle={false}
onClick={() => setSubmenuOpen(!submenuOpen)}
>
<i className="ni ni-world" />
<span>Choose Language</span>
</DropdownItem>
{submenuOpen && (
<div className="dropdown-menu show">
<DropdownItem onClick={() => handleLanguageSelect("en")}>English</DropdownItem>
<DropdownItem onClick={() => handleLanguageSelect("hi")}>Hindi</DropdownItem>
<DropdownItem onClick={() => handleLanguageSelect("ta")}>Tamil</DropdownItem>
<DropdownItem onClick={() => handleLanguageSelect("te")}>Telugu</DropdownItem>
</div>
)}
</div>
<DropdownItem to="/admin/resetpassword" tag={Link}>
<i className="ni ni-lock-circle-open" />
<span>Reset Password</span>
</DropdownItem> </DropdownItem>
<DropdownItem divider /> <DropdownItem divider />
<DropdownItem onClick={handleLogout}> <DropdownItem onClick={handleLogout}>
<i className="ni ni-user-run" /> <i className="ni ni-user-run" />
<span>Logout</span> <span>Logout</span>
</DropdownItem> </DropdownItem>
</DropdownMenu>
</UncontrolledDropdown> </DropdownMenu>
</Nav> </UncontrolledDropdown>
</Nav>
</div>
{ /* Mobile Right Sidebar */}
<div className="nav-right-mobile d-flex d-lg-none align-items-center ml-auto">
<Nav className="align-items-center" navbar>
<UncontrolledDropdown nav>
<DropdownToggle className="pr-0" nav>
<Media className="align-items-center">
<span className="avatar avatar-sm rounded-circle">
<FontAwesomeIcon icon={faUser} />
</span>
</Media>
</DropdownToggle>
<DropdownMenu className="dropdown-menu-arrow" right>
<DropdownItem header tag="div">
<h6 className="text-overflow m-0">Welcome!</h6>
</DropdownItem>
<DropdownItem to="/admin/profile" tag={Link}>
<i className="ni ni-single-02" />
<span>My profile</span>
</DropdownItem>
<DropdownItem to="/admin/dashboard-runner-all" tag={Link}>
<i className="ni ni-calendar-grid-58" />
<span>Activity</span>
</DropdownItem>
<DropdownItem to="/admin/resetpassword" tag={Link}>
<i className="ni ni-lock-circle-open" />
<span>Reset Password</span>
</DropdownItem>
<DropdownItem divider />
<DropdownItem onClick={handleLogout}>
<i className="ni ni-user-run" />
<span>Logout</span>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</div>
</div> </div>
</div> </Navbar>
</Navbar>
{/* Mobile Sidebar */}
<div className={`mobile-right-sidebar ${sidebarOpen ? 'open' : ''}`}>
<Link to="/admin/index" className="nav-icon" onClick={toggleSidebar}>
<i className="fas fa-home" />
</Link>
<Link to="/admin/setting" className="nav-icon" onClick={toggleSidebar}>
<i className="ni ni-settings-gear-65" /> </Link>
<Link to="/admin/dashboard-runner-all" className="nav-icon" onClick={toggleSidebar}>
<i className="bi bi-grid" />
</Link>
<Link to="/admin/report-runner" className="nav-icon" onClick={toggleSidebar}>
<i className="ni ni-chart-bar-32" />
</Link>
<Link to="/admin/user-report" className="nav-icon" onClick={toggleSidebar}>
<i className="ni ni-grid" />
</Link>
</div>
</>
); );
const handleLanguageSelect = (lang) => {
localStorage.setItem("appLanguage", lang);
setSubmenuOpen(false); // Close submenu
document.body.click(); // Close parent dropdown
window.location.reload(); // Or use i18n if configured
};
}; };
export default AdminNavbar;
export default AdminNavbar;

View File

@ -77,10 +77,10 @@
/* Adjust main content margin when sidebar is expanded/collapsed */ /* Adjust main content margin when sidebar is expanded/collapsed */
.main-content { .main-content {
margin-left: 250px; margin-left:250px;
transition: margin-left 0.3s ease; transition: margin-left 0.3s ease;
} }
.main-content.sidebar-collapsed-main { .main-content.sidebar-collapsed-main {
margin-left: 50px; margin-left: 60px;
} }

View File

@ -1,54 +1,18 @@
import { useState, useEffect } from "react"; import { useState } from "react";
import { Link, useLocation } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Sidebar as ProSidebar, Menu, MenuItem, SubMenu } from "react-pro-sidebar"; import {
import { fetchMenuItems } from "../../APIServices/MenuAPI"; Sidebar as ProSidebar,
import routes from "routes.js"; Menu,
MenuItem,
SubMenu,
} from "react-pro-sidebar";
import { FaChevronLeft, FaChevronRight, FaDatabase, FaExclamationCircle } from "react-icons/fa";
import "../Sidebar/Sidebar.css"; import "../Sidebar/Sidebar.css";
const Sidebar = (props) => { const Sidebar = (props) => {
const [menuItems, setMenuItems] = useState([]); const [collapsed, setCollapsed] = useState(true);
const [collapsed, setCollapsed] = useState(false); const navigate = useNavigate();
const [error, setError] = useState("");
const location = useLocation();
useEffect(() => {
loadMenuItems();
}, []);
const loadMenuItems = async () => {
try {
const respdata = await fetchMenuItems();
const data = respdata.data;
if (Array.isArray(data)) {
const dynamicRoutes = mapMenuToRoutes(data);
setMenuItems(dynamicRoutes);
} else if (data && typeof data === "object") {
const dynamicRoutes = mapMenuToRoutes([data]);
setMenuItems(dynamicRoutes);
} else {
console.error("Invalid menu data format:", data);
setError("Invalid menu data format.");
}
} catch (err) {
console.error("Error fetching menu items:", err);
setError(err.message || "Failed to fetch menu items.");
}
};
const mapMenuToRoutes = (menuArray) => {
if (!Array.isArray(menuArray)) {
console.error('Expected an array for menuArray, received:', menuArray);
return [];
}
return menuArray.map(menu => ({
path: menu.path || '#',
name: menu.name || menu.menuName || '',
icon: menu.icon || 'bi bi-grid',
submenu: Array.isArray(menu.submenu) ? mapMenuToRoutes(menu.submenu) : []
}));
};
const toggleSidebar = () => { const toggleSidebar = () => {
setCollapsed(!collapsed); setCollapsed(!collapsed);
@ -57,71 +21,41 @@ const Sidebar = (props) => {
} }
}; };
const renderMenuItems = () => {
const allRoutes = [...routes, ...menuItems];
return allRoutes.map((route, key) => {
if (route.submenu && route.submenu.length > 0) {
return (
<SubMenu
key={key}
label={route.name}
icon={<i className={route.icon} />}
>
{route.submenu.map((submenu, subKey) => (
<MenuItem
key={`${key}-${subKey}`}
component={<Link to={submenu.path} />}
icon={<i className={submenu.icon || "bi bi-grid"} />}
>
{submenu.name}
</MenuItem>
))}
</SubMenu>
);
}
return (
<MenuItem
key={key}
component={<Link to={route.path} />}
icon={<i className={route.icon || "bi bi-grid"} />}
>
{route.name}
</MenuItem>
);
});
};
const { logo } = props;
return ( return (
<div className="sidebar-wrapper"> <div className="sidebar-wrapper">
<ProSidebar <ProSidebar
collapsed={collapsed} collapsed={collapsed}
className="app-sidebar" className="app-sidebar"
backgroundColor="white" backgroundColor="#e8e8e8"
width="220px" width="220px"
collapsedWidth="30px" collapsedWidth="30px"
> >
<div className="sidebar-header"> <div className="sidebar-header d-flex justify-content-end px-2 pt-2">
{/* {logo && (
<Link to={logo.innerLink} className="logo-container">
<img alt={logo.imgAlt} className="navbar-brand-img" src={logo.imgSrc} />
</Link>
)} */}
<button <button
className="sidebar-toggle-btn" className="sidebar-toggle-btn btn btn-link p-0"
type="button"
onClick={toggleSidebar} onClick={toggleSidebar}
title={collapsed ? "Expand sidebar" : "Collapse sidebar"} title={collapsed ? "Expand sidebar" : "Collapse sidebar"}
> >
<i className={`bi ${collapsed ? "bi-chevron-right" : "bi-chevron-left"}`} /> {collapsed ? <FaChevronRight /> : <FaChevronLeft />}
</button> </button>
</div> </div>
<Menu> <Menu>
{renderMenuItems()} <SubMenu label="Transactions" icon={<FaExclamationCircle />}>
<MenuItem onClick={() => navigate("/admin/regform")}>
Regform
</MenuItem>
<MenuItem onClick={() => navigate("/admin/error404")}>
Additional container
</MenuItem>
</SubMenu>
<MenuItem
icon={<FaDatabase />}
onClick={() => navigate("/admin/error404")}
>
Masters
</MenuItem>
</Menu> </Menu>
</ProSidebar> </ProSidebar>
</div> </div>
@ -137,4 +71,4 @@ Sidebar.propTypes = {
onSidebarToggle: PropTypes.func, onSidebarToggle: PropTypes.func,
}; };
export default Sidebar; export default Sidebar;

View File

@ -70,7 +70,7 @@ const Admin = (props) => {
> >
{/* This is where the nested routes will render */} {/* This is where the nested routes will render */}
<div className="px-0" style={{ marginTop: "100px" }}> <div className="px-0" style={{ marginTop: "7rem" }}>
<Outlet /> <Outlet />
</div> </div>

View File

@ -19,7 +19,7 @@
// import AccessTypeManagement from "components/Dashboard/AccessType"; // import AccessTypeManagement from "components/Dashboard/AccessType";
// import APIRegistry from "components/Dashboard/APIRegistry"; // import APIRegistry from "components/Dashboard/APIRegistry";
// import TOKENRegistry from "components/Dashboard/TOKENRegistry"; // import TOKENRegistry from "components/Dashboard/TOKENRegistry";
// import DataType1 from "components/Dashboard/DataType1"; // import SequenceGenerator from "components/Dashboard/sequencegenerator";
// import DataType2 from "components/Dashboard/DataType2"; // import DataType2 from "components/Dashboard/DataType2";
// import DataType3 from "components/Dashboard/DataType3"; // import DataType3 from "components/Dashboard/DataType3";
// import DataType4 from "components/Dashboard/DataType4"; // import DataType4 from "components/Dashboard/DataType4";
@ -210,7 +210,7 @@
// path: "/datatype-1", // path: "/datatype-1",
// name: "Datatype-1", // name: "Datatype-1",
// icon: "fa-solid fa-utensils", // icon: "fa-solid fa-utensils",
// component: <DataType1/>, // should be a component function or class // component: <sequencegenerator/>, // should be a component function or class
// layout: "/admin", // layout: "/admin",
// showInSidebar: false // showInSidebar: false
// }, // },
@ -284,7 +284,7 @@ import MenuMaintenance from "components/Dashboard/MenuMaintenance";
import AccessTypeManagement from "components/Dashboard/AccessType"; import AccessTypeManagement from "components/Dashboard/AccessType";
import APIRegistry from "components/Dashboard/APIRegistry"; import APIRegistry from "components/Dashboard/APIRegistry";
import TOKENRegistry from "components/Dashboard/TOKENRegistry"; import TOKENRegistry from "components/Dashboard/TOKENRegistry";
import DataType1 from "components/Dashboard/DataType1"; import SequenceGenerator from "components/Dashboard/sequencegenerator";
import DataType2 from "components/Dashboard/DataType2"; import DataType2 from "components/Dashboard/DataType2";
import DataType3 from "components/Dashboard/DataType3"; import DataType3 from "components/Dashboard/DataType3";
import DataType4 from "components/Dashboard/DataType4"; import DataType4 from "components/Dashboard/DataType4";
@ -448,7 +448,7 @@ var routes = [
path: "/admin/datatype-1", path: "/admin/datatype-1",
name: "Datatype-1", name: "Datatype-1",
icon: "fa-solid fa-utensils", icon: "fa-solid fa-utensils",
component: <DataType1/>, // should be a component function or class component: <SequenceGenerator/>, // should be a component function or class
layout: "/admin", layout: "/admin",
showInSidebar: false showInSidebar: false
}, },

View File

@ -81,285 +81,285 @@ const Index = (props) => {
setChartExample1Data("data" + index); setChartExample1Data("data" + index);
}; };
return ( return (
<>Home Page</> // <>Home Page</>
// <div > <div >
// <Header /> <Header />
// <Sidebar menuData={menuData} /> <Sidebar menuData={menuData} />
// {/* Page content */} {/* Page content */}
// <Container className="mt--7" fluid style={{ marginTop: "-4rem" }}> <Container className="mt--7" fluid style={{ marginTop: "-4rem" }}>
// <Row> <Row>
// <Col className="mb-5 mb-xl-0" xl="8"> <Col className="mb-5 mb-xl-0" xl="8">
// <Card className="bg-gradient-default shadow"> <Card className="bg-gradient-default shadow">
// <CardHeader className="bg-transparent"> <CardHeader className="bg-transparent">
// <Row className="align-items-center"> <Row className="align-items-center">
// <div className="col"> <div className="col">
// <h6 className="text-uppercase text-light ls-1 mb-1"> <h6 className="text-uppercase text-light ls-1 mb-1">
// Overview Overview
// </h6> </h6>
// <h2 className="text-white mb-0">Sales value</h2> <h2 className="text-white mb-0">Sales value</h2>
// </div> </div>
// <div className="col"> <div className="col">
// <Nav className="justify-content-end" pills> <Nav className="justify-content-end" pills>
// <NavItem> <NavItem>
// <NavLink <NavLink
// className={classnames("py-2 px-3", { className={classnames("py-2 px-3", {
// active: activeNav === 1, active: activeNav === 1,
// })} })}
// href="#pablo" href="#pablo"
// onClick={(e) => toggleNavs(e, 1)} onClick={(e) => toggleNavs(e, 1)}
// > >
// <span className="d-none d-md-block">Month</span> <span className="d-none d-md-block">Month</span>
// <span className="d-md-none">M</span> <span className="d-md-none">M</span>
// </NavLink> </NavLink>
// </NavItem> </NavItem>
// <NavItem> <NavItem>
// <NavLink <NavLink
// className={classnames("py-2 px-3", { className={classnames("py-2 px-3", {
// active: activeNav === 2, active: activeNav === 2,
// })} })}
// data-toggle="tab" data-toggle="tab"
// href="#pablo" href="#pablo"
// onClick={(e) => toggleNavs(e, 2)} onClick={(e) => toggleNavs(e, 2)}
// > >
// <span className="d-none d-md-block">Week</span> <span className="d-none d-md-block">Week</span>
// <span className="d-md-none">W</span> <span className="d-md-none">W</span>
// </NavLink> </NavLink>
// </NavItem> </NavItem>
// </Nav> </Nav>
// </div> </div>
// </Row> </Row>
// </CardHeader> </CardHeader>
// <CardBody> <CardBody>
// {/* Chart */} {/* Chart */}
// <div className="chart"> <div className="chart">
// {chartExample1[chartExample1Data] ? ( {chartExample1[chartExample1Data] ? (
// <Line <Line
// data={chartExample1[chartExample1Data]} data={chartExample1[chartExample1Data]}
// options={chartExample1.options} options={chartExample1.options}
// /> />
// ) : ( ) : (
// <p>Loading chart...</p> <p>Loading chart...</p>
// )} )}
// </div> </div>
// </CardBody> </CardBody>
// </Card> </Card>
// </Col> </Col>
// <Col xl="4"> <Col xl="4">
// <Card className="shadow"> <Card className="shadow">
// <CardHeader className="bg-transparent"> <CardHeader className="bg-transparent">
// <Row className="align-items-center"> <Row className="align-items-center">
// <div className="col"> <div className="col">
// <h6 className="text-uppercase text-muted ls-1 mb-1"> <h6 className="text-uppercase text-muted ls-1 mb-1">
// Performance Performance
// </h6> </h6>
// <h2 className="mb-0">Total orders</h2> <h2 className="mb-0">Total orders</h2>
// </div> </div>
// </Row> </Row>
// </CardHeader> </CardHeader>
// <CardBody> <CardBody>
// {/* Chart */} {/* Chart */}
// <div className="chart"> <div className="chart">
// <Bar <Bar
// data={chartExample2.data} data={chartExample2.data}
// options={chartExample2.options} options={chartExample2.options}
// /> />
// </div> </div>
// </CardBody> </CardBody>
// </Card> </Card>
// </Col> </Col>
// </Row> </Row>
// <Row className="mt-5"> <Row className="mt-5">
// <Col className="mb-5 mb-xl-0" xl="8"> <Col className="mb-5 mb-xl-0" xl="8">
// <Card className="shadow"> <Card className="shadow">
// <CardHeader className="border-0"> <CardHeader className="border-0">
// <Row className="align-items-center"> <Row className="align-items-center">
// <div className="col"> <div className="col">
// <h3 className="mb-0">Page visits</h3> <h3 className="mb-0">Page visits</h3>
// </div> </div>
// <div className="col text-right"> <div className="col text-right">
// <Button <Button
// color="primary" color="primary"
// href="#pablo" href="#pablo"
// onClick={(e) => e.preventDefault()} onClick={(e) => e.preventDefault()}
// size="sm" size="sm"
// > >
// See all See all
// </Button> </Button>
// </div> </div>
// </Row> </Row>
// </CardHeader> </CardHeader>
// <Table className="align-items-center table-flush" responsive> <Table className="align-items-center table-flush" responsive>
// <thead className="thead-light"> <thead className="thead-light">
// <tr> <tr>
// <th scope="col">Page name</th> <th scope="col">Page name</th>
// <th scope="col">Visitors</th> <th scope="col">Visitors</th>
// <th scope="col">Unique users</th> <th scope="col">Unique users</th>
// <th scope="col">Bounce rate</th> <th scope="col">Bounce rate</th>
// </tr> </tr>
// </thead> </thead>
// <tbody> <tbody>
// <tr> <tr>
// <th scope="row">/argon/</th> <th scope="row">/argon/</th>
// <td>4,569</td> <td>4,569</td>
// <td>340</td> <td>340</td>
// <td> <td>
// <i className="fas fa-arrow-up text-success mr-3" /> 46,53% <i className="fas fa-arrow-up text-success mr-3" /> 46,53%
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">/argon/index.html</th> <th scope="row">/argon/index.html</th>
// <td>3,985</td> <td>3,985</td>
// <td>319</td> <td>319</td>
// <td> <td>
// <i className="fas fa-arrow-down text-warning mr-3" />{" "} <i className="fas fa-arrow-down text-warning mr-3" />{" "}
// 46,53% 46,53%
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">/argon/charts.html</th> <th scope="row">/argon/charts.html</th>
// <td>3,513</td> <td>3,513</td>
// <td>294</td> <td>294</td>
// <td> <td>
// <i className="fas fa-arrow-down text-warning mr-3" />{" "} <i className="fas fa-arrow-down text-warning mr-3" />{" "}
// 36,49% 36,49%
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">/argon/tables.html</th> <th scope="row">/argon/tables.html</th>
// <td>2,050</td> <td>2,050</td>
// <td>147</td> <td>147</td>
// <td> <td>
// <i className="fas fa-arrow-up text-success mr-3" /> 50,87% <i className="fas fa-arrow-up text-success mr-3" /> 50,87%
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">/argon/profile.html</th> <th scope="row">/argon/profile.html</th>
// <td>1,795</td> <td>1,795</td>
// <td>190</td> <td>190</td>
// <td> <td>
// <i className="fas fa-arrow-down text-danger mr-3" />{" "} <i className="fas fa-arrow-down text-danger mr-3" />{" "}
// 46,53% 46,53%
// </td> </td>
// </tr> </tr>
// </tbody> </tbody>
// </Table> </Table>
// </Card> </Card>
// </Col> </Col>
// <Col xl="4"> <Col xl="4">
// <Card className="shadow"> <Card className="shadow">
// <CardHeader className="border-0"> <CardHeader className="border-0">
// <Row className="align-items-center"> <Row className="align-items-center">
// <div className="col"> <div className="col">
// <h3 className="mb-0">Social traffic</h3> <h3 className="mb-0">Social traffic</h3>
// </div> </div>
// <div className="col text-right"> <div className="col text-right">
// <Button <Button
// color="primary" color="primary"
// href="#pablo" href="#pablo"
// onClick={(e) => e.preventDefault()} onClick={(e) => e.preventDefault()}
// size="sm" size="sm"
// > >
// See all See all
// </Button> </Button>
// </div> </div>
// </Row> </Row>
// </CardHeader> </CardHeader>
// <Table className="align-items-center table-flush" responsive> <Table className="align-items-center table-flush" responsive>
// <thead className="thead-light"> <thead className="thead-light">
// <tr> <tr>
// <th scope="col">Referral</th> <th scope="col">Referral</th>
// <th scope="col">Visitors</th> <th scope="col">Visitors</th>
// <th scope="col" /> <th scope="col" />
// </tr> </tr>
// </thead> </thead>
// <tbody> <tbody>
// <tr> <tr>
// <th scope="row">Facebook</th> <th scope="row">Facebook</th>
// <td>1,480</td> <td>1,480</td>
// <td> <td>
// <div className="d-flex align-items-center"> <div className="d-flex align-items-center">
// <span className="mr-2">60%</span> <span className="mr-2">60%</span>
// <div> <div>
// <Progress <Progress
// max="100" max="100"
// value="60" value="60"
// barClassName="bg-gradient-danger" barClassName="bg-gradient-danger"
// /> />
// </div> </div>
// </div> </div>
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">Facebook</th> <th scope="row">Facebook</th>
// <td>5,480</td> <td>5,480</td>
// <td> <td>
// <div className="d-flex align-items-center"> <div className="d-flex align-items-center">
// <span className="mr-2">70%</span> <span className="mr-2">70%</span>
// <div> <div>
// <Progress <Progress
// max="100" max="100"
// value="70" value="70"
// barClassName="bg-gradient-success" barClassName="bg-gradient-success"
// /> />
// </div> </div>
// </div> </div>
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">Google</th> <th scope="row">Google</th>
// <td>4,807</td> <td>4,807</td>
// <td> <td>
// <div className="d-flex align-items-center"> <div className="d-flex align-items-center">
// <span className="mr-2">80%</span> <span className="mr-2">80%</span>
// <div> <div>
// <Progress max="100" value="80" /> <Progress max="100" value="80" />
// </div> </div>
// </div> </div>
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">Instagram</th> <th scope="row">Instagram</th>
// <td>3,678</td> <td>3,678</td>
// <td> <td>
// <div className="d-flex align-items-center"> <div className="d-flex align-items-center">
// <span className="mr-2">75%</span> <span className="mr-2">75%</span>
// <div> <div>
// <Progress <Progress
// max="100" max="100"
// value="75" value="75"
// barClassName="bg-gradient-info" barClassName="bg-gradient-info"
// /> />
// </div> </div>
// </div> </div>
// </td> </td>
// </tr> </tr>
// <tr> <tr>
// <th scope="row">twitter</th> <th scope="row">twitter</th>
// <td>2,645</td> <td>2,645</td>
// <td> <td>
// <div className="d-flex align-items-center"> <div className="d-flex align-items-center">
// <span className="mr-2">30%</span> <span className="mr-2">30%</span>
// <div> <div>
// <Progress <Progress
// max="100" max="100"
// value="30" value="30"
// barClassName="bg-gradient-warning" barClassName="bg-gradient-warning"
// /> />
// </div> </div>
// </div> </div>
// </td> </td>
// </tr> </tr>
// </tbody> </tbody>
// </Table> </Table>
// </Card> </Card>
// </Col> </Col>
// </Row> </Row>
// </Container> </Container>
// </div> </div>
); );
}; };

View File

@ -0,0 +1,34 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Button } from 'react-bootstrap';
const Error404 = () => {
const navigate = useNavigate();
return (
<div
className="d-flex flex-column justify-content-center align-items-center vh-100"
style={{ backgroundColor: '#f7f7f7' }}
>
<div className="text-center">
<div style={{ fontSize: '80px', color: '#f44336' }}>
<span style={{ fontSize: '100px' }}>🛡</span>
</div>
<h1 style={{ color: 'red', fontWeight: 'bold' }}>error 404</h1>
<p style={{ color: '#555', fontSize: '18px' }}>
Not found your page requested.
</p>
<Button
variant="primary"
className="mt-4"
onClick={() => navigate('/admin/index')} // Adjust path if needed
>
Go to home
</Button>
</div>
</div>
);
};
export default Error404;

View File

@ -1,329 +1,325 @@
/*! // // // reactstrap components
// // import {
// // Button,
// // Card,
// // CardHeader,
// // CardBody,
// // FormGroup,
// // Form,
// // Input,
// // Container,
// // Row,
// // Col,
// // } from "reactstrap";
// // // core components
// // import UserHeader from "components/Headers/UserHeader.js";
========================================================= // // const Profile = () => {
* Argon Dashboard React - v1.2.4 // // return (
========================================================= // // <>
// // <UserHeader />
// // {/* Page content */}
// // {/* <Container className="mt--7" fluid>
// // <Row>
// // <Col xl="12">
// // <Card className="bg-secondary shadow">
// // <CardHeader className="bg-white border-0">
// // <Row className="align-items-center">
// // <Col xs="8">
// // <h3 className="mb-0">My Profile Settings</h3>
// // </Col>
// // </Row>
// // </CardHeader>
// // <CardBody>
// // <Form>
// // <Row>
// // <Col md="6">
// // <FormGroup>
// // <label>Your Full Name</label>
// // <Input placeholder="Enter full name" type="text" />
// // </FormGroup>
// // </Col>
// // <Col md="6">
// // <FormGroup>
// // <label>Pronouns</label>
// // <Input placeholder="Enter pronouns" type="text" />
// // </FormGroup>
// // </Col>
// // </Row>
// // <Row>
// // <Col md="6">
// // <FormGroup>
// // <label>Role</label>
// // <Input placeholder="Enter role" type="text" />
// // </FormGroup>
// // </Col>
// // <Col md="6">
// // <FormGroup>
// // <label>Department or Team</label>
// // <Input placeholder="Enter department" type="text" />
// // </FormGroup>
// // </Col>
// // </Row>
// // <Row>
// // <Col md="12">
// // <FormGroup>
// // <label>Email</label>
// // <Input placeholder="Enter email" type="email" />
// // </FormGroup>
// // </Col>
// // </Row>
// // <FormGroup>
// // <label>About Me</label>
// // <Input
// // type="textarea"
// // rows="4"
// // placeholder="Enter description"
// // />
// // </FormGroup>
// // <Button color="primary" type="submit">
// // Update
// // </Button>
// // </Form>
// // </CardBody>
// // </Card>
// // </Col>
// // </Row>
// // </Container>*/}
// // </>
// // );
// // };
* Product Page: https://www.creative-tim.com/product/argon-dashboard-react // // export default Profile;
* Copyright 2024 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://github.com/creativetimofficial/argon-dashboard-react/blob/master/LICENSE.md)
* Coded by Creative Tim // import React from 'react';
// import { Link, useNavigate } from 'react-router-dom';
// import 'bootstrap/dist/css/bootstrap.min.css';
========================================================= // const Profile = () => {
// const navigate = useNavigate();
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // const handleLogout = () => {
// // Clear user session/token and redirect to login or homepage
// localStorage.removeItem("authToken");
// navigate('/auth/login');
// };
*/ // return (
// <div className="container mt-5">
// <h3 className="mb-4">My Profile Settings</h3>
// reactstrap components // <div className="mb-3">
import { // <label>Your Full Name</label>
Button, // <input type="text" className="form-control" value="sysadmin" readOnly />
Card, // </div>
CardHeader,
CardBody, // <div className="mb-3">
FormGroup, // <label>Pronouns</label>
Form, // <input type="text" className="form-control" placeholder="Enter Pronouns" />
Input, // </div>
Container,
Row, // <div className="mb-3">
Col, // <label>Role</label>
} from "reactstrap"; // <input type="text" className="form-control" placeholder="Enter Role" />
// core components // </div>
import UserHeader from "components/Headers/UserHeader.js";
// <div className="mb-3">
// <label>Department or Team</label>
// <input type="text" className="form-control" placeholder="Enter Department" />
// </div>
// <div className="mb-3">
// <label>Email</label>
// <input type="email" className="form-control" value="sysadmin" readOnly />
// </div>
// <div className="mb-3">
// <label>About Me</label>
// <textarea className="form-control" placeholder="Enter Description"></textarea>
// </div>
// <button
// className="btn btn-primary mb-4"
// onClick={() => navigate('/error404')}
// >
// Update
// </button>
// <hr />
// <p><strong>Password:</strong> Change Password for your account <Link to="/auth/resetpassword">Change password</Link></p>
// <hr />
// <p><strong>Security:</strong> Logout of all sessions except this current browser <span style={{ color: 'blue', cursor: 'pointer' }} onClick={handleLogout}>Logout other sessions</span></p>
// <hr />
// <p><strong>Deactivation:</strong> Remove access to all organizations and workspace in CloudnSure <span style={{ color: 'blue', cursor: 'pointer' }} onClick={handleLogout}>Deactivate account</span></p>
// </div>
// );
// };
// export default Profile;
import React, { useState, useRef } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
const Profile = () => { const Profile = () => {
const navigate = useNavigate();
const [preview, setPreview] = useState(null);
const [selectedFile, setSelectedFile] = useState(null);
const fileInputRef = useRef(null);
const handleLogout = () => {
localStorage.removeItem("authToken");
navigate('/auth/login');
};
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
setSelectedFile(file);
const reader = new FileReader();
reader.onloadend = () => {
setPreview(reader.result);
};
reader.readAsDataURL(file);
}
};
const triggerFileInput = () => {
fileInputRef.current.click();
};
const handleCancel = () => {
setPreview(null);
setSelectedFile(null);
fileInputRef.current.value = '';
};
const handleUpload = () => {
if (!selectedFile) return;
// Here you would typically upload the file to your server
// For example:
// const formData = new FormData();
// formData.append('profileImage', selectedFile);
// fetch('/api/upload-profile-image', {
// method: 'POST',
// body: formData
// })
// .then(response => response.json())
// .then(data => {
// console.log('Upload successful', data);
// })
// .catch(error => {
// console.error('Upload error', error);
// });
alert('Upload functionality would go here');
};
return ( return (
<> <div className="container mt-5">
<UserHeader /> <h3 className="mb-4">My Profile Settings</h3>
{/* Page content */}
<Container className="mt--7" fluid> {/* Simple Image Upload Section */}
<Row> <div className="mb-4">
<Col className="order-xl-2 mb-5 mb-xl-0" xl="4"> <h5>PROFILE PHOTO</h5>
<Card className="card-profile shadow"> <div className="d-flex align-items-center mb-3">
<Row className="justify-content-center"> <div className="me-3">
<Col className="order-lg-2" lg="3"> {preview ? (
<div className="card-profile-image"> <img
<a href="#pablo" onClick={(e) => e.preventDefault()}> src={preview}
<img alt="Profile Preview"
alt="..." style={{ width: '100px', height: '100px', borderRadius: '50%', objectFit: 'cover' }}
className="rounded-circle" />
src={require("../../assets/img/theme/team-4-800x800.jpg")} ) : (
/> <div style={{ width: '100px', height: '100px', borderRadius: '50%', backgroundColor: '#f0f0f0' }}></div>
</a> )}
</div> </div>
</Col> <div>
</Row> <input
<CardHeader className="text-center border-0 pt-8 pt-md-4 pb-0 pb-md-4"> type="file"
<div className="d-flex justify-content-between"> ref={fileInputRef}
<Button onChange={handleFileChange}
className="mr-4" accept="image/*"
color="info" style={{ display: 'none' }}
href="#pablo" />
onClick={(e) => e.preventDefault()} <button className="btn btn-outline-primary" onClick={triggerFileInput}>
size="sm" Choose File
> </button>
Connect </div>
</Button> </div>
<Button
className="float-right" {/* Action buttons - shown only when an image is selected */}
color="default" {preview && (
href="#pablo" <div className="d-flex justify-content-end gap-2 mt-3">
onClick={(e) => e.preventDefault()} <button className="btn btn-outline-secondary" onClick={handleCancel}>
size="sm" Cancel
> </button>
Message <button className="btn btn-primary" onClick={handleUpload}>
</Button> Upload
</div> </button>
</CardHeader> </div>
<CardBody className="pt-0 pt-md-4"> )}
<Row> </div>
<div className="col">
<div className="card-profile-stats d-flex justify-content-center mt-md-5"> {/* Rest of the profile form */}
<div> <div className="mb-3">
<span className="heading">22</span> <label>Your Full Name</label>
<span className="description">Friends</span> <input type="text" className="form-control" value="sysadmin" readOnly />
</div> </div>
<div>
<span className="heading">10</span> <div className="mb-3">
<span className="description">Photos</span> <label>Pronouns</label>
</div> <input type="text" className="form-control" placeholder="Enter Pronouns" />
<div> </div>
<span className="heading">89</span>
<span className="description">Comments</span> <div className="mb-3">
</div> <label>Role</label>
</div> <input type="text" className="form-control" placeholder="Enter Role" />
</div> </div>
</Row>
<div className="text-center"> <div className="mb-3">
<h3> <label>Department or Team</label>
Jessica Jones <input type="text" className="form-control" placeholder="Enter Department" />
<span className="font-weight-light">, 27</span> </div>
</h3>
<div className="h5 font-weight-300"> <div className="mb-3">
<i className="ni location_pin mr-2" /> <label>Email</label>
Bucharest, Romania <input type="email" className="form-control" value="sysadmin" readOnly />
</div> </div>
<div className="h5 mt-4">
<i className="ni business_briefcase-24 mr-2" /> <div className="mb-3">
Solution Manager - Creative Tim Officer <label>About Me</label>
</div> <textarea className="form-control" placeholder="Enter Description"></textarea>
<div> </div>
<i className="ni education_hat mr-2" />
University of Computer Science <button
</div> className="btn btn-primary mb-4"
<hr className="my-4" /> onClick={() => navigate('/error404')}
<p> >
Ryan the name taken by Melbourne-raised, Brooklyn-based Update Profile
Nick Murphy writes, performs and records all of his own </button>
music.
</p> <hr />
<a href="#pablo" onClick={(e) => e.preventDefault()}>
Show more <p><strong>Password:</strong> Change Password for your account <Link to="/admin/resetpassword">Change password</Link></p>
</a>
</div> <hr />
</CardBody>
</Card> <p><strong>Security:</strong> Logout of all sessions except this current browser <span style={{ color: 'blue', cursor: 'pointer' }} onClick={handleLogout}>Logout other sessions</span></p>
</Col>
<Col className="order-xl-1" xl="8"> <hr />
<Card className="bg-secondary shadow">
<CardHeader className="bg-white border-0"> <p><strong>Deactivation:</strong> Remove access to all organizations and workspace in CloudnSure <span style={{ color: 'blue', cursor: 'pointer' }} onClick={handleLogout}>Deactivate account</span></p>
<Row className="align-items-center"> </div>
<Col xs="8">
<h3 className="mb-0">My account</h3>
</Col>
<Col className="text-right" xs="4">
<Button
color="primary"
href="#pablo"
onClick={(e) => e.preventDefault()}
size="sm"
>
Settings
</Button>
</Col>
</Row>
</CardHeader>
<CardBody>
<Form>
<h6 className="heading-small text-muted mb-4">
User information
</h6>
<div className="pl-lg-4">
<Row>
<Col lg="6">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-username"
>
Username
</label>
<Input
className="form-control-alternative"
defaultValue="lucky.jesse"
id="input-username"
placeholder="Username"
type="text"
/>
</FormGroup>
</Col>
<Col lg="6">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-email"
>
Email address
</label>
<Input
className="form-control-alternative"
id="input-email"
placeholder="jesse@example.com"
type="email"
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col lg="6">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-first-name"
>
First name
</label>
<Input
className="form-control-alternative"
defaultValue="Lucky"
id="input-first-name"
placeholder="First name"
type="text"
/>
</FormGroup>
</Col>
<Col lg="6">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-last-name"
>
Last name
</label>
<Input
className="form-control-alternative"
defaultValue="Jesse"
id="input-last-name"
placeholder="Last name"
type="text"
/>
</FormGroup>
</Col>
</Row>
</div>
<hr className="my-4" />
{/* Address */}
<h6 className="heading-small text-muted mb-4">
Contact information
</h6>
<div className="pl-lg-4">
<Row>
<Col md="12">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-address"
>
Address
</label>
<Input
className="form-control-alternative"
defaultValue="Bld Mihail Kogalniceanu, nr. 8 Bl 1, Sc 1, Ap 09"
id="input-address"
placeholder="Home Address"
type="text"
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col lg="4">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-city"
>
City
</label>
<Input
className="form-control-alternative"
defaultValue="New York"
id="input-city"
placeholder="City"
type="text"
/>
</FormGroup>
</Col>
<Col lg="4">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-country"
>
Country
</label>
<Input
className="form-control-alternative"
defaultValue="United States"
id="input-country"
placeholder="Country"
type="text"
/>
</FormGroup>
</Col>
<Col lg="4">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-country"
>
Postal code
</label>
<Input
className="form-control-alternative"
id="input-postal-code"
placeholder="Postal code"
type="number"
/>
</FormGroup>
</Col>
</Row>
</div>
<hr className="my-4" />
{/* Description */}
<h6 className="heading-small text-muted mb-4">About me</h6>
<div className="pl-lg-4">
<FormGroup>
<label>About Me</label>
<Input
className="form-control-alternative"
placeholder="A few words about you ..."
rows="4"
defaultValue="A beautiful Dashboard for Bootstrap 4. It is Free and
Open Source."
type="textarea"
/>
</FormGroup>
</div>
</Form>
</CardBody>
</Card>
</Col>
</Row>
</Container>
</>
); );
}; };
export default Profile; export default Profile;

View File

@ -0,0 +1,23 @@
// src/views/examples/about.js
import React from "react";
const About = () => (
<div className="text-center p-4">
<img
src="https://your-domain.com/about-image.png"
alt="About Us"
onError={(e) => {
e.target.onerror = null;
e.target.src = "https://via.placeholder.com/300x200?text=About+Image";
}}
style={{ width: "300px", height: "200px", objectFit: "cover" }}
/>
<h1 className="text-4xl font-bold text-blue-600">About Us</h1>
<p className="mt-4 text-lg text-gray-600">
Create new project for new users if you have access. If you don't have access, please contact the admin.
</p>
</div>
);
export default About;

View File

@ -0,0 +1,89 @@
import React, { useState, useEffect } from "react";
import { Table, Button } from "react-bootstrap";
import { FaFilter } from "react-icons/fa";
const Regform = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
const dummyData = [
{
name: "kk",
rollNumber: "101",
date: "2025-05-19",
email: "kab@dekatc.com",
},
{
name: "b",
rollNumber: "1",
date: "2025-05-24",
email: "kab@gmail.com",
},
];
setTimeout(() => {
setData(dummyData);
setLoading(false);
}, 500);
};
fetchData();
}, []);
return (
<div className="container mt-5">
<h3 className="mb-4">Registration Records</h3>
{loading ? (
<div className="text-center my-4">Loading...</div>
) : (
<>
{data.length === 0 ? (
<div className="text-center my-4">No data available</div>
) : (
<Table striped bordered hover responsive>
<thead className="table-light">
<tr>
<th>
<input type="checkbox" disabled />
</th>
<th>
Name <FaFilter className="ms-1" />
</th>
<th>
Roll Number <FaFilter className="ms-1" />
</th>
<th>
Date Field <FaFilter className="ms-1" />
</th>
<th>Email Field</th>
</tr>
</thead>
<tbody>
{data.map((entry, index) => (
<tr key={index}>
<td>
<input type="checkbox" />
</td>
<td>{entry.name}</td>
<td>{entry.rollNumber}</td>
<td>{entry.date}</td>
<td>{entry.email}</td>
</tr>
))}
</tbody>
</Table>
)}
</>
)}
<Button variant="outline-secondary" className="mt-3">
Manage Columns
</Button>
</div>
);
};
export default Regform;

View File

@ -1,140 +1,105 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { FaEye, FaEyeSlash } from 'react-icons/fa';
import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap/dist/css/bootstrap.min.css';
function ResetPassword() { const ResetPassword = () => {
const [email, setEmail] = useState(''); const [oldPassword, setOldPassword] = useState('');
const [message, setMessage] = useState(''); const [newPassword, setNewPassword] = useState('');
const [error, setError] = useState(''); const [reenterPassword, setReenterPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const navigate = useNavigate();
const handleEmailChange = (e) => { const isFormValid =
setEmail(e.target.value); oldPassword.trim() &&
}; newPassword.trim().length >= 3 &&
reenterPassword.trim();
const handleSubmit = async (e) => { const toggleShowPassword = () => {
e.preventDefault(); setShowPassword(!showPassword);
setMessage(""); };
setError("");
const token = localStorage.getItem("authToken");
if (!token) {
setError("Authorization token is missing.");
return;
}
try {
const response = await fetch(`${process.env.REACT_APP_API_URL}api/resources/forgotpassword`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ email }),
});
const data = await response.json();
if (response.ok) {
setMessage("A reset link has been sent to your email address.");
} else {
setError(data.message || "There was an issue sending the reset link. Please try again.");
}
} catch (error) {
setError("An error occurred. Please try again later.");
}
};
return (
// <div className="position-fixed top-0 start-0 w-100 h-100 d-flex justify-content-center align-items-center" style={{ backgroundColor: 'gray' }}>
// <div className="card p-5" style={{ borderRadius: '15px', width: '100%', maxWidth: '500px' }}>
// <h5 className="text-center mb-4">Forgot My Username and Password</h5>
// <p className="text-center mb-4">
// By signing up, I agree to the CloudnSure <a href="/privacy-policy" target="_blank" rel="noopener noreferrer"><u>Privacy Policy</u></a> and <a href="/terms-of-service" target="_blank" rel="noopener noreferrer"><u>Terms of Service</u></a>.
// </p>
// <form onSubmit={handleSubmit}>
// <div className="form-group mb-3">
// <label htmlFor="email">Email Address:</label>
// <input
// type="email"
// id="email"
// className="form-control"
// value={email}
// onChange={handleEmailChange}
// required
// />
// </div>
// <button type="submit" className="btn btn-block mb-2" style={{backgroundColor:" #007bff"}}>Send Reset Link</button>
// </form>
// {message && <p className="text-success text-center mt-3">{message}</p>}
// {error && <p className="text-danger text-center mt-3">{error}</p>}
// </div>
// </div>
<div const handleSubmit = (e) => {
className="position-fixed top-0 start-0 w-100 h-100" e.preventDefault();
style={{ navigate('/error404'); // Assuming your route path is /error404
backgroundColor: 'rgba(128, 128, 128, -0.1)', // Full-page background with slight transparency };
zIndex: 1, // Ensure background is behind the card
}} return (
>
<div
className="d-flex justify-content-center align-items-center h-100"
style={{
position: 'relative', // Ensures proper stacking
zIndex: 2, // Ensures card stays above background
}}
>
<div <div
className="card shadow-lg p-5" className="d-flex justify-content-center align-items-center vh-100"
style={{ style={{ backgroundColor: '#f7f7f7' }}
borderRadius: '15px',
width: '100%',
maxWidth: '500px',
backgroundColor: '#fff', // Explicit white background for card
zIndex: 3, // Card always stays on top
}}
> >
<h5 className="text-center mb-4">Forgot My Username and Password</h5> <div
<p className="text-center mb-4"> className="p-5 shadow bg-white rounded"
By signing up, I agree to the CloudnSure{' '} style={{ maxWidth: '500px', width: '100%' }}
<a href="/privacy-policy" target="_blank" rel="noopener noreferrer"> >
<u>Privacy Policy</u> <h3 className="text-center mb-3">Please Reset Your Password</h3>
</a>{' '} <p className="text-center text-muted mb-4">you're signed in as sysadmin</p>
and{' '}
<a href="/terms-of-service" target="_blank" rel="noopener noreferrer">
<u>Terms of Service</u>
</a>.
</p>
<form onSubmit={handleSubmit}>
<div className="form-group mb-3">
<label htmlFor="email">Email Address:</label>
<input
type="email"
id="email"
className="form-control"
value={email}
onChange={handleEmailChange}
required
/>
</div>
<button
type="submit"
className="btn btn-block mb-2"
style={{
backgroundColor: '#007bff',
color: '#fff',
}}
>
Send Reset Link
</button>
</form>
{message && <p className="text-success text-center mt-3">{message}</p>}
{error && <p className="text-danger text-center mt-3">{error}</p>}
</div>
</div>
</div>
<form onSubmit={handleSubmit}>
); {[
} { label: 'Enter Old Password', value: oldPassword, setter: setOldPassword },
{ label: 'Enter New Password', value: newPassword, setter: setNewPassword },
{ label: 'Re-Enter New Password', value: reenterPassword, setter: setReenterPassword },
].map(({ label, value, setter }, index) => (
<div key={index} className="form-group position-relative mb-3">
<label>{label}</label>
<input
type={showPassword ? 'text' : 'password'}
className="form-control"
placeholder={label}
value={value}
onChange={(e) => setter(e.target.value)}
/>
<span
className="position-absolute"
onClick={toggleShowPassword}
style={{
top: '38px',
right: '15px',
cursor: 'pointer',
color: '#999',
}}
>
{showPassword ? <FaEyeSlash /> : <FaEye />}
</span>
</div>
))}
<button
type="submit"
className="btn w-100"
style={{
backgroundColor: isFormValid ? '#6c63ff' : '#d6d6ff',
color: '#fff',
textTransform: 'uppercase',
letterSpacing: '1px',
}}
disabled={!isFormValid}
>
Continue
</button>
</form>
<div className="d-flex justify-content-between mt-4">
<button
className="btn btn-outline-primary w-50 me-2"
onClick={() => navigate('/admin/index')}
>
Go to Home
</button>
<button
className="btn btn-outline-primary w-50 ms-2"
onClick={() => navigate('/auth/login')}
>
Login
</button>
</div>
</div>
</div>
);
};
export default ResetPassword; export default ResetPassword;