Skip to content

Commit

Permalink
Merge pull request #129 from suvarnakale/release-3.1.0.0
Browse files Browse the repository at this point in the history
Issue #125  Feat: nAdmin - Role and Dashboard Implementation
  • Loading branch information
Sowmya-Raghuram authored Jan 30, 2025
2 parents b4e7f46 + 0b7da98 commit caaaa53
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 2 deletions.
64 changes: 64 additions & 0 deletions src/main/frontend/src/components/CommonComponents/FilterBy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import {
Box,
MenuItem,
Select,
Checkbox,
ListItemText,
Typography,
InputLabel,
FormControl,
} from "@mui/material";

const FilterBy = ({ options, onFilterChange, label = "Filter By" }) => {
const [selectedValues, setSelectedValues] = useState(["All"]);

const handleChange = (event) => {
const value = event.target.value;
setSelectedValues(value);
onFilterChange(value);
};

return (
<Box sx={{ width: "100%" }}>
<FormControl fullWidth>
<InputLabel
id="demo-simple-select-label"
component="legend"
variant="outlined"
>
{label}
</InputLabel>
<Select
labelId="demo-simple-select-label"
multiple
value={selectedValues}
onChange={handleChange}
renderValue={(selected) => selected.join(", ")}
>
{options.map((option) => (
<MenuItem key={option} value={option}>
<Checkbox checked={selectedValues.includes(option)} />
<ListItemText primary={option} />
</MenuItem>
))}
</Select>
</FormControl>
</Box>
);
};

// Prop validation
FilterBy.propTypes = {
options: PropTypes.arrayOf(PropTypes.string).isRequired,
onFilterChange: PropTypes.func.isRequired,
label: PropTypes.string,
};

// Default props
FilterBy.defaultProps = {
label: "Filter By",
};

export default FilterBy;
65 changes: 65 additions & 0 deletions src/main/frontend/src/components/CommonComponents/NeedCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
import PropTypes from "prop-types";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

const NeedCard = ({ matrixData }) => {
if (!matrixData || matrixData.length === 0) {
return (
<Typography variant="body1" color="text.secondary">
No data available
</Typography>
);
}

return (
<Box display="flex" flexWrap="wrap" gap="1rem">
{matrixData?.map((matrix, index) => (
<Box
key={index}
sx={{
width: { xs: "100%", sm: "48%", md: "32%", lg: "24%" },
maxWidth: "16rem",
}}
>
<Card variant="outlined">
<CardContent>
<Box display="flex" gap="1rem" alignItems="center">
<Box>
<img
src={matrix.icon || ""}
alt={matrix.status || "Nominated Needs"}
height="30px"
style={{ objectFit: "contain" }}
/>
</Box>
<Box>
<Typography variant="h4" component="div">
{matrix.count || 0}
</Typography>
<Typography sx={{ color: "text.secondary" }}>
{matrix.status || "Status"}
</Typography>
</Box>
</Box>
</CardContent>
</Card>
</Box>
))}
</Box>
);
};

NeedCard.propTypes = {
matrixData: PropTypes.arrayOf(
PropTypes.shape({
icon: PropTypes.string,
count: PropTypes.number,
status: PropTypes.string,
})
),
};

export default NeedCard;
37 changes: 37 additions & 0 deletions src/main/frontend/src/components/CommonComponents/sampleData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import VolunteerNeedsNominated from "../../assets/needsNominated.png";
import VolunteerNeedsInProgress from "../../assets/needsInProgress.png";
import VolunteerNeedsApproved from "../../assets/needsApproved.png";
import VolunteerPlansDelivered from "../../assets/plansDelivered.png";

export const matrixData = [
{
icon: VolunteerNeedsNominated,
count: 200,
status: "Total Needs Created",
},
{
icon: VolunteerNeedsInProgress,
count: 8,
status: "Needs in Progress",
},
{
icon: VolunteerNeedsApproved,
count: 24,
status: "Needs Requested",
},
{
icon: VolunteerNeedsApproved,
count: 12,
status: "Needs Approved",
},
{
icon: VolunteerPlansDelivered,
count: 280,
status: "Total Volunteers",
},
{
icon: VolunteerNeedsInProgress,
count: 80,
status: "New Volunteers",
},
];
2 changes: 1 addition & 1 deletion src/main/frontend/src/components/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function Header({ toggleSideNav, role }) {
backgroundColor: avatarColor,
}}
>
{currentUser.email.slice(0, 1).toUpperCase()}
{currentUser?.email.slice(0, 1).toUpperCase()}
</Avatar>
</div>
</button>
Expand Down
6 changes: 5 additions & 1 deletion src/main/frontend/src/containers/MainPage/MainPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import "./MainPage.css";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import SideNav from "../../components/SideNav/SideNav";
import Header from "../../components/Header/Header";
import Dashboard from "../../components/Dashboard/Dashboard";
import Needs from "../../components/Needs/Needs";
import RaiseNeed from "../../components/RaiseNeed/RaiseNeed";
import NeedPlans from "../../components/Need Plans/NeedPlans";
Expand All @@ -15,6 +14,7 @@ import { useSelector } from "react-redux";
import CircularProgress from "@mui/material/CircularProgress";
import NoRoleAssigned from "../../components/NoRoleAssigned/NoRoleAssigned";
import Registration from "../../components/Registration/Registration";
import Dashboard from "../nAdmin/Dashboard";
const MainPage = () => {
const [isSideNavOpen, setIsSideNavOpen] = useState(false);
const [role, setRole] = useState("");
Expand Down Expand Up @@ -57,6 +57,9 @@ const MainPage = () => {
render={() => {
if (role === "nCoordinator") {
return <Redirect to="/needs" />;
} else if (role === "nAdmin") {
return <Redirect to="/nAdmin-dashboard" />;
} else if (role) {
} else if (role === undefined) {
return <Redirect to="/no-role" />;
} else if (role) {
Expand All @@ -73,6 +76,7 @@ const MainPage = () => {
<Route path="/help" component={Help} />
<Route path="/no-role" component={NoRoleAssigned} />
<Route path="/vregistration" component={Registration} />
<Route path="/nAdmin-dashboard" component={Dashboard} />
</Switch>
</div>
</div>
Expand Down
56 changes: 56 additions & 0 deletions src/main/frontend/src/containers/nAdmin/Dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { useState } from "react";
import NeedCard from "../../components/CommonComponents/NeedCard";
import FilterBy from "../../components/CommonComponents/FilterBy";
import { matrixData } from "../../components/CommonComponents/sampleData";
import { Box, Typography } from "@mui/material";
import NeedsTable from "../../components/NeedsTable/NeedsTable";
const Dashboard = () => {
const [filteredData, setFilteredData] = useState([]);

const handleFilterChange = (selectedFilters) => {
console.log("Selected Filters:", selectedFilters);
setFilteredData(selectedFilters);
};

return (
<Box padding={"1rem"}>
<Box
padding={"1rem"}
gap={"0.5rem"}
display={"flex"}
width={"100%"}
justifyContent={"space-between"}
>
<Box>
<Box display={"flex"} gap={"0.5rem"}>
<Typography variant="body1" color="text.secondary">
Welcome Back,
</Typography>
<Typography variant="body1" color="text.primary">
DemoAdmin!
</Typography>
</Box>
<Typography variant="h4" color="text.primary">
Dashboard
</Typography>
<Typography variant="body1" color="text.secondary">
Here's your needs analytics data
</Typography>
</Box>

<Box width={"20%"} marginTop={"3rem"}>
<FilterBy
options={["All", "Option 1", "Option 2", "Option 3", "Option 4"]}
onFilterChange={handleFilterChange}
/>
</Box>
</Box>
<NeedCard matrixData={matrixData} />
<Box bgcolor={"white"}>
<NeedsTable />
</Box>
</Box>
);
};

export default Dashboard;

0 comments on commit caaaa53

Please sign in to comment.