Skip to content

Commit

Permalink
CompanyWall assignment upload
Browse files Browse the repository at this point in the history
  • Loading branch information
nesic998 authored Nov 27, 2023
0 parents commit d4198f6
Show file tree
Hide file tree
Showing 30 changed files with 3,904 additions and 0 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
26 changes: 26 additions & 0 deletions components/ui/Input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { TextField, styled } from "@mui/material";

const Input = styled(TextField)({
"& label": {
color: "black",
},
"& label.Mui-focused": {
color: "#4b9388",
},
"& .MuiInput-underline:after": {
borderBottomColor: "#B2BAC2",
},
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#E0E3E7",
},
"&:hover fieldset": {
borderColor: "#B2BAC2",
},
"&.Mui-focused fieldset": {
borderColor: "#6F7E8C",
},
},
});

export default Input;
24 changes: 24 additions & 0 deletions components/ui/Navbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";

export default function Navbar() {
const router = useRouter();

return (
<nav className="nav-items">
<ul>
<li className={`${router.pathname === "/" ? "active" : ""} fs-20`}>
<Link href="/">Home</Link>
</li>
<li className={`${router.pathname === "/roles" ? "active" : ""} fs-20`}>
{" "}
<Link href="/roles">Roles</Link>
</li>
<li className={`${router.pathname === "/users" ? "active" : ""} fs-20`}>
<Link href="/users">Users</Link>
</li>
</ul>
</nav>
);
}
37 changes: 37 additions & 0 deletions components/ui/RoleValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export const validateField = (fieldName, value, setErrors, errors) => {
let errorMessage = "";

switch (fieldName) {
case "roleName":
errorMessage = validateRoleName(value);
break;
case "roleDescription":
errorMessage = validateRoleDescription(value);
break;
default:
break;
}

setErrors((prevErrors) => ({
...prevErrors,
[fieldName]: errorMessage,
}));
};

const validateRoleName = (value) => {
if (!value) {
return "Role name is required.";
}
if (!/^[a-zA-Z0-9_]{2,16}$/.test(value)) {
return "Role name must be alphanumeric and can contain underscores (_), min length of 2, max length of 16 characters.";
}

return "";
};

const validateRoleDescription = (value) => {
if (value.length > 50) {
return "Role description must be at most 50 characters.";
}
return "";
};
214 changes: 214 additions & 0 deletions components/ui/TableGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";

import Image from "next/image";

import editIcon from "../../public/images/edit.svg";
import Link from "next/link";
import { Button, TablePagination, TableSortLabel } from "@mui/material";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

export default function TableGenerator() {
const router = useRouter();

const [orderBy, setOrderBy] = useState("roleName");
const [order, setOrder] = useState("asc");

const [page, setPage] = useState(0); // Added state for current page
const [rowsPerPage, setRowsPerPage] = useState(10); // Added state for rows per page

const handleChangePage = (event, newPage) => {
setPage(newPage);
};

const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};

const [data, setData] = useState([]);

const handleSortRequest = (property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};

const stableSort = (array, comparator) => {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
};

const getComparator = (order, orderBy) => {
return order === "desc"
? (a, b) => descendingComparator(a[orderBy], b[orderBy])
: (a, b) => -descendingComparator(a[orderBy], b[orderBy]);
};

const descendingComparator = (a, b) => {
if (b < a || a === null) return -1;
if (a < b || b === null) return 1;
return 0;
};

const createSortHandler = (property) => (event) => {
handleSortRequest(property);
};

useEffect(() => {
if (router.pathname === "/roles") {
const fetchData = async () => {
try {
const response = await fetch("/api/roles");
const data = await response.json();
setData(data.roles);
} catch (error) {
console.error("Error fetching roles:", error);
}
};

fetchData();
} else {
setOrderBy("id");
setOrder("desc");

const fetchData = async () => {
try {
const response = await fetch("/api/users");
const data = await response.json();
setData(data.roles);
} catch (error) {
console.error("Error fetching roles:", error);
}
};

fetchData();
}
}, []);

return (
<TableContainer component={Paper}>
<Link
style={{ textDecoration: "none", color: "red", marginBottom: "20px" }}
href={router.pathname === "/roles" ? "/roles/create" : "/users/create"}
>
<Button
sx={{ m: "20px 0px 20px 30px" }}
color="success"
variant="contained"
>
Create
</Button>
</Link>

<Table className="table" sx={{ minWidth: 400 }} aria-label="simple table">
<TableHead>
<TableRow>
{router.pathname === "/roles" ? (
<>
<TableCell>
<TableSortLabel
active={orderBy === "roleName"}
direction={orderBy === "roleName" ? order : "asc"}
onClick={createSortHandler("roleName")}
>
Role Name
</TableSortLabel>
</TableCell>
<TableCell>Role description</TableCell>
<TableCell>Actions</TableCell>
</>
) : router.pathname === "/users" ? (
<>
<TableCell>
{" "}
<TableSortLabel
active={orderBy === "id"}
direction={orderBy === "id" ? order : "desc"}
onClick={createSortHandler("id")}
>
Row number
</TableSortLabel>
</TableCell>

<TableCell>First name</TableCell>
<TableCell>Last name</TableCell>
<TableCell>Email address</TableCell>
<TableCell>Role name</TableCell>
<TableCell>Actions</TableCell>
</>
) : null}
</TableRow>
</TableHead>
<TableBody>
{stableSort(data, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) // Added slicing based on current page and rowsPerPage
.map((row) => (
<TableRow key={row.id}>
{router.pathname === "/roles" ? (
<>
<TableCell>{row.roleName}</TableCell>
<TableCell>{row.roleDescription}</TableCell>
<TableCell>
<Link href={`/roles/update/${row.id}`}>
<Image
style={{
width: "20px",
height: "20px",
cursor: "pointer",
}}
alt="update"
src={editIcon}
></Image>{" "}
</Link>
</TableCell>
</>
) : router.pathname === "/users" ? (
<>
<TableCell>{row.id}</TableCell>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.emailAddress}</TableCell>
<TableCell>{row.roleName}</TableCell>
<TableCell>
<Link href={`/users/update/${row.id}`}>
<Image
style={{
width: "20px",
height: "20px",
cursor: "pointer",
}}
alt="update"
src={editIcon}
></Image>{" "}
</Link>
</TableCell>
</>
) : null}
</TableRow>
))}
</TableBody>
</Table>
<TablePagination
rowsPerPageOptions={[10, 25, 50]} // Customize rows per page options as needed
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</TableContainer>
);
}
Loading

0 comments on commit d4198f6

Please sign in to comment.