Skip to content

Commit

Permalink
Merge pull request #46 from fga-eps-mds/208-listagem-de-usuario
Browse files Browse the repository at this point in the history
(#208) Página de listagem de usuário
  • Loading branch information
lipeaaraujo authored Dec 11, 2023
2 parents cecde81 + 35f19ac commit 994f084
Show file tree
Hide file tree
Showing 24 changed files with 2,278 additions and 698 deletions.
1,310 changes: 687 additions & 623 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest --coverage --passWithNoTests --no-cache --runInBand",
"test": "jest --passWithNoTests --no-cache --runInBand --bail",
"test:all": "CI=true npm run test -- --coverage",
"test:watch": "react-scripts test",
"eject": "react-scripts eject",
Expand Down
Binary file added public/Log.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>PrintGO</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
Binary file added public/logo--.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/logo192.png
Binary file not shown.
Binary file removed public/logo512.png
Binary file not shown.
10 changes: 8 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import CreateUserPage from "./pages/CreateUser";
import EditUserPage from "./pages/EditUser";
import UsersList from "./pages/UsersList";
import Login from "./pages/Login";
import Contact from "./pages/Contact";
import AboutUs from "./pages/AboutUs";
Expand All @@ -19,23 +20,28 @@ import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import RecoverPasswordPage from "./pages/RecoverPassword";
import PrivateRoutes from "./components/utils/PrivateRoutes";
import AdminRoutes from "./components/utils/AdminRoutes";

function App() {
return (
<>
<BrowserRouter>
<Routes>
<Route element={<PrivateRoutes />}>
<Route path="/cadastro" element={<CreateUserPage />} />
<Route path="/editarusuario" element={<EditUserPage/>}/>
<Route path="/editarusuario/:id" element={<EditUserPage/>}/>
<Route path="/mudarsenha" element={<ChangePassword />} />
<Route path="/cadastroimpressora" element={<RegisterPrinter />} />
<Route path="/editarimpressora" element={<EditPrinter />} />
<Route path="/padraoimpressora" element={<PatternPrinter />} />
<Route path="/editarpadrao/:padrao" element={<EditPattern />} />
<Route path="/impressorascadastradas" element={<PrintersList />} />
<Route path="/listapadroes" element={<PatternList />} />
<Route path="/padroescadastrados" element={<PatternList />} />
<Route path="/visualizarpadrao/:padrao" element={<ViewPattern />} />
<Route element={<AdminRoutes/>}>
<Route path="/listausuarios" element={<UsersList />} />
<Route path="/cadastro" element={<CreateUserPage />} />
</Route>
</Route>
<Route path="/login" element={<Login />} />
<Route path="/" element={<Home />} />
Expand Down
5 changes: 5 additions & 0 deletions src/assets/Profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 121 additions & 44 deletions src/components/forms/EditUserForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,37 @@ import React, { useEffect, useState, useMemo } from "react";
import { useForm } from "react-hook-form";
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import * as yup from "yup";
import { getUnidades } from "../../services/unidadeService";
import { getUserById, updateUser } from "../../services/userService";
import "../../style/components/editUserForms.css";
import { ReloadIcon } from "@radix-ui/react-icons";
import { Link, useNavigate } from 'react-router-dom';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { decodeToken } from "react-jwt";
import { getEditUserSchema } from "../utils/YupSchema";

const fieldLabels = {
nome: 'Nome',
documento: 'CPF',
email: 'Email',
emailConfirmar: 'Email',
unidade_id: "Unidade",
};

const editUserSchema = yup.object().shape({
nome: yup.string().required('Nome é obrigatório'),
email: yup
.string()
.email('Email inválido')
.required('Email é obrigatório'),
emailConfirmar: yup
.string()
.oneOf([yup.ref('email'), null], 'Os emails devem coincidir')
.required('Email é obrigatória'),
documento: yup.string()
.matches(/^(\d{11}|\d{14})$/, 'CPF ou CNPJ inválido')
.test('cpfOrCnpj', 'CPF ou CNPJ inválido', value => {
return value.length === 11 || value.length === 14;
}),
unidade_id: yup.string().required('Lotação é obrigatória'),
unidade_pai: yup.string().strip(),
});
const testObject = {
nome: 'Fulano',
documento: '01234567890',
email: 'email@email.com',
emailConfirmar: 'email@email.com',
};

export default function EditUserForm(){
const { id } = useParams();

const editUserSchema = getEditUserSchema(fieldLabels);
const { register, setValue, handleSubmit, formState: { errors, isValid, isSubmitting } } = useForm({
resolver: yupResolver(editUserSchema),
mode: "onChange"
});

let loggedUser = null;
const token = localStorage.getItem("jwt");
Expand All @@ -40,42 +42,68 @@ export default function EditUserForm(){
}

const [unidadeList, setUnidadeList] = useState();
const [isEditingAnotherAdmin, setIsEditingAnotherAdmin] = useState(); //verifica se o usuario que esta sendo editado eh admin
const [isLocadora, setIsLocadora] = useState(); //verifica se o usuario que esta sendo editado eh da locadora
const [displayLotacoes,setDisplayLotacoes] = useState ('');
const [unidadeFilhoList, setUnidadeFilhoList] = useState ();
const [userData, setUserData] = useState(null);
const [displayUserRole, setDisplayUserRole] = useState(true);

const memoUserData = useMemo(() => userData, [userData]);
const memoUnidadeList = useMemo(() => unidadeList, [unidadeList]);

const navigate = useNavigate();

const handleCheckboxLocadoraChange = (event) => {
setIsLocadora(event.target.checked);
};

const {
register,
setValue,
handleSubmit,
formState: { errors, isValid, isSubmitting },
reset
} = useForm({resolver: yupResolver(editUserSchema), mode: "onChange"})
const handleCheckboxAdminChange = (event) =>{
setIsEditingAnotherAdmin(event.target.checked);
}

const navigate = useNavigate();

// Puxe os dados do usuário logado.
useEffect(() => {
const fetchUserData = async () => {
try {
const data = await getUserById(loggedUser.id);
const data = await getUserById(id);

console.log(data);
if (data) {
setUserData(data);
if(data.cargos.includes("ADMIN")){
setIsEditingAnotherAdmin(true);
}
if(data.cargos.includes("LOCADORA")){
setIsLocadora(true);
}
}
} catch(error) {
console.log('Erro ao buscar dados do usuário:', error);
}
}
if(loggedUser && !userData) {
fetchUserData();

const verifyUser = async () =>{
if(loggedUser && !userData) {
await fetchUserData();

if(loggedUser.cargos.includes("ADMIN")) {
if(loggedUser.id === id){
setDisplayUserRole(false);
}
else{
return;
}
} else if(loggedUser.id != id) {
navigate("/"); // Um usuário comum não pode editar outro usuário além dele mesmo.
} else {
setDisplayUserRole(false);
}

}
}

verifyUser();

}, [loggedUser])

// Puxe os dados das unidades policiais.
Expand All @@ -98,11 +126,14 @@ export default function EditUserForm(){

useEffect(() => {
if (memoUserData && memoUnidadeList && unidadeList) {
console.log(unidadeList);

Object.keys(userData).forEach((key) => {
setValue(key, userData[key] || "");
Object.keys(editUserSchema.fields).forEach((key) => {
if (userData[key]) {
setValue(key, userData[key]);
}
})

isEditingAnotherAdmin ? setValue("isAdmin", true) : setValue("isAdmin", false);
isLocadora ? setValue("isLocadora", true) : setValue("isLocadora", false);

const unidadeFilha = unidadeList.find(unidade => unidade.id === userData.unidade_id);

Expand All @@ -118,19 +149,34 @@ export default function EditUserForm(){
}, [memoUserData, memoUnidadeList, setValue]);

const onSubmit = async (data) => {
data.id = id;

data.cargos = ["USER"]

if (data.isAdmin) {
data.cargos = data.cargos || [];
data.cargos.push("ADMIN")
}

if (data.isLocadora) {
data.cargos = data.cargos || [];
data.cargos.push("LOCADORA")
}

delete data["isAdmin"];
delete data["isLocadora"];
delete data["emailConfirmar"];
delete data["unidade_pai"];

console.log(data);

setTimeout(() => {
console.log("3 segundos se passaram.");
}, 3000); // 3000 milissegundos = 3 segundos

delete data["emailConfirmar"];
delete data["unidade_pai"];

const response = await updateUser(data, data.id);
if(response.type === 'success'){
toast.success("Usuario atualizado com sucesso!");
reset()
} else {
toast.error("Erro ao atualizar usuário");
}
Expand All @@ -152,7 +198,8 @@ export default function EditUserForm(){
};

return(
<div id="edit-user-card" data-testid="edit-user-card">
<div id="edit-user-card">
<Link id="link-back" to="/listausuarios">Voltar</Link>
<header id="edit-user-form-header">
Editar usuário
</header>
Expand Down Expand Up @@ -227,12 +274,40 @@ export default function EditUserForm(){
</div>

</div>
{displayUserRole && (
<div id="edit-user-input-line">
<div id="edit-user-input-box">
<div id="edit-user-input-checkbox" data-testid="admin-checkbox">
<input
id="checkbox"
type="checkbox"
{...register("isAdmin")}
onChange={handleCheckboxAdminChange}
/>

<label htmlFor="label-checkbox" id="label-checkbox">Usuário é administrador?</label>
</div>
</div>
<div id="edit-user-input-box">
<div id="edit-user-input-checkbox" data-testid="locadora-checkbox">
<input
id="checkbox"
type="checkbox"
{...register("isLocadora")}
onChange={handleCheckboxLocadoraChange}
/>
<label htmlFor="label-checkbox" id="label-checkbox">Usuário é da Locadora?</label>
</div>
</div>
</div>
)}


<div id="edit-user-buttons">
<button className="edit-user-form-button" type="button" id="edit-user-cancel-bnt">
<Link to="/">CANCELAR</Link>
<Link to="#">CANCELAR</Link>
</button>
<button className="edit-user-form-button" type="submit" id="edit-user-register-bnt" disabled={!isValid || isSubmitting}>
<button className="edit-user-form-button" type="submit" id="edit-user-register-bnt" disabled={isSubmitting || !isValid}>
{isSubmitting && (
<ReloadIcon id="animate-spin" data-testid="animate-spin"/>
)}
Expand All @@ -245,3 +320,5 @@ export default function EditUserForm(){
</div>
);
}

export { fieldLabels, testObject };
22 changes: 17 additions & 5 deletions src/components/navbar/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ const Navbar = () => {

let navigate = useNavigate();

const isTokenExpired = (decodedToken) =>{
if (!decodedToken || Date.now() >= decodedToken.exp * 1000) {
console.log("token expirou")
return true; // Token expirado
}
else {
return false;
}
}

const toggleUserDropdown = () => {
setUserDropdownOpen(!userDropdownOpen)
}
Expand All @@ -25,6 +35,9 @@ const Navbar = () => {
const token = localStorage.getItem("jwt");
if (token) {
user = decodeToken(token);
if(isTokenExpired(user)){
user = null
}
}

const userLogOut = async (e) => {
Expand All @@ -36,8 +49,6 @@ const Navbar = () => {
catch(error){
console.log(error)
}


}

return (
Expand All @@ -57,14 +68,15 @@ const Navbar = () => {

{ user && (
<>
{ user.cargos.includes('ADMIN') && (
{ user.cargos?.includes('ADMIN') && (
<div className="navbar-users">
<button className="navbar-users-button" onClick={toggleUserDropdown}>
<h4>Usuários</h4>
<FiChevronDown />
{userDropdownOpen && (
<div className="navbar-users-dropdown">
<Link to="/cadastro">Cadastro de usuário</Link>
<Link to='/listausuarios'>Usuários cadastrados</Link>
</div>
)}
</button>
Expand Down Expand Up @@ -94,7 +106,7 @@ const Navbar = () => {
<div className="navbar-user-info">
<div className="navbar-user-message">
<img alt="loggeduser" src={LoggedUser}/>
<Link to={"/editarusuario"}>Olá, {user.nome}!</Link>
<Link to={`/editarusuario/${user.id}`}>Olá, {user.nome}!</Link>
</div>
<Link className="navbar-user-leave" data-testid="navbar-leave-button" onClick={userLogOut}>
<button>
Expand All @@ -117,4 +129,4 @@ const Navbar = () => {
</div>
);
};
export default Navbar;
export default Navbar;
Loading

0 comments on commit 994f084

Please sign in to comment.