Skip to content

Commit

Permalink
feat: Add user menu with option to add new user
Browse files Browse the repository at this point in the history
  • Loading branch information
edmdz committed Aug 14, 2024
1 parent 28e2f40 commit 95499e1
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 254 deletions.
Binary file added src/assets/adduser.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/components/NavigationBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const staticTitles = {
"/products/brands/models": "Modelos",
"/products/brands/models/radiators": "Radiadores",
"/providers": "Proveedores",
"/users": "Gestion de usuarios",
"/users/add-user": "Agregar usuario",
};

const NavigationBar = () => {
Expand Down
259 changes: 259 additions & 0 deletions src/pages/Users/UserCreation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
import { useState } from 'react';
import {
Container, Grid, Typography, Button, TextField, FormControl, InputLabel, Select, MenuItem,
InputAdornment, IconButton, Alert
} from '@mui/material';
import dayjs from 'dayjs';
import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import VisibilityIcon from '@mui/icons-material/Visibility';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../../services/Firebase/firebase';
import validateEmail from '../../util/EmailVerifier';
import { createUser } from '../../services/UserService';
import Person from '../../models/Person';
import User from '../../models/User';
import { useSnackbar } from '../../components/SnackbarContext';

export default function UserCreation() {
const [userData, setUserData] = useState({
firstName: '',
lastName: '',
email: '',
phoneNumber: '',
address: '',
birthDate: dayjs(),
password: '',
confirmPassword: '',
active: 1,
roleId: ''
});
const [passwordsMatch, setPasswordsMatch] = useState(true);
const [showPasswords, setShowPasswords] = useState(false);
const { openSnackbar } = useSnackbar(); // Usa el hook del Snackbar

const handleDateChange = (newValue) => {
setUserData({ ...userData, birthDate: newValue });
};

const handleInputChange = (event) => {
const { name, value } = event.target;
setUserData({ ...userData, [name]: value });
};

const handleConfirmPasswordBlur = () => {
const arePasswordsMatching = userData.confirmPassword === userData.password;
setPasswordsMatch(arePasswordsMatching);
};

const handleTogglePasswordVisibility = () => {
setShowPasswords(!showPasswords);
};

const handlePhoneNumberChange = (event) => {
let inputValue = event.target.value.replace(/\D/g, ''); // Elimina todos los caracteres que no sean números
inputValue = inputValue.slice(0, 10); // Limita la longitud a 10 dígitos
setUserData({ ...userData, phoneNumber: inputValue });
};

const handleSubmit = async () => {
if (!validateEmail(userData.email)) {
openSnackbar('El correo electrónico no es válido.', 'error');
return;
}

try {
const userCredential = await createUserWithEmailAndPassword(auth, userData.email, userData.password);
const userId = userCredential.user.uid;
const user = new User({
id: userId,
person: new Person({
name: userData.firstName,
lastName: userData.lastName,
email: userData.email,
phoneNumber: userData.phoneNumber,
address: userData.address,
birthDate: userData.birthDate.toISOString(),
active: userData.active
}),
roleId: userData.roleId
});

await createUser(user);

openSnackbar('¡Usuario creado correctamente!', 'success');
setUserData({
firstName: '',
lastName: '',
email: '',
phoneNumber: '',
address: '',
birthDate: dayjs(),
active: 1,
password: '',
confirmPassword: '',
roleId: ''
});
} catch (error) {
openSnackbar('Error al registrar usuario en Firebase.', 'error');
}
};

const areAllFieldsComplete = () => {
return Object.values(userData).every(value => value !== '') && passwordsMatch;
};

return (
<Container style={{ display: 'flex', flexDirection: 'column', height: '100%', paddingTop: '10vh' }}>
<Typography variant="h4" align="center" gutterBottom>Registro de usuario</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
required
name="firstName"
label="Nombres"
value={userData.firstName}
onChange={handleInputChange}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
name="lastName"
label="Apellidos"
value={userData.lastName}
onChange={handleInputChange}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth style={{ width: '100%' }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label="Fecha de nacimiento"
value={userData.birthDate}
onChange={handleDateChange}
renderInput={(params) => (
<TextField
{...params}
type="text"
placeholder="Seleccione una fecha"
fullWidth
/>
)}
/>
</LocalizationProvider>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
required
name="phoneNumber"
label="Teléfono"
value={userData.phoneNumber}
onChange={handlePhoneNumberChange}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
name="address"
label="Dirección"
value={userData.address}
onChange={handleInputChange}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
required
name="email"
label="Email"
value={userData.email}
onChange={handleInputChange}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
required
name="password"
label="Contraseña"
type={showPasswords ? 'text' : 'password'} // Mostrar texto si showPasswords es verdadero
value={userData.password}
onChange={handleInputChange}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleTogglePasswordVisibility}>
{showPasswords ? <VisibilityOffIcon /> : <VisibilityIcon />}
</IconButton>
</InputAdornment>
)
}}
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<TextField
required
name="confirmPassword"
label="Confirmar Contraseña"
type={showPasswords ? 'text' : 'password'}
value={userData.confirmPassword}
onChange={handleInputChange}
onBlur={handleConfirmPasswordBlur}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleTogglePasswordVisibility}>
{showPasswords ? <VisibilityOffIcon /> : <VisibilityIcon />}
</IconButton>
</InputAdornment>
)
}}
/>
{!passwordsMatch && (
<Alert
sx={{ marginTop: '0.5rem' }}
severity="error"
>
Las contraseñas no coinciden.
</Alert>
)}
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl fullWidth>
<InputLabel id="label" required>Selecciona Rol</InputLabel>
<Select
value={userData.roleId}
onChange={handleInputChange}
label="Seleccione una opción"
name="roleId"
fullWidth
>
<MenuItem value="1">Administrador</MenuItem>
<MenuItem value="2">Empleado</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
</Grid>
<Grid item xs={12} style={{ textAlign: 'end', marginTop: '16px' }}>
<Button variant="contained" color="primary" onClick={handleSubmit} disabled={!areAllFieldsComplete()}>
Registrar
</Button>
</Grid>
</Grid>
</Container>
);
}
48 changes: 48 additions & 0 deletions src/pages/Users/UserMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Grid from '@mui/material/Grid';
import Card from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea';
import CardMedia from '@mui/material/CardMedia';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
import AddUserImg from '/src/assets/adduser.png';

const UserMenu = ({ onOptionSelect }) => {
const options = [
{
id: 'add-user',
title: 'Agregar Usuario',
imageUrl: AddUserImg, // Reemplaza esto con la ruta de la imagen adecuada
description: 'Añade un nuevo usuario al sistema',
},
// Agrega más opciones aquí si es necesario en el futuro
];

return (
<Grid container spacing={4}>
{options.map((option) => (
<Grid item xs={12} sm={6} md={4} key={option.id}>
<Card>
<CardActionArea onClick={() => onOptionSelect(option.id)}>
<CardMedia
component="img"
height="140"
image={option.imageUrl}
alt={option.title}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{option.title}
</Typography>
<Typography variant="body2" color="text.secondary">
{option.description}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
))}
</Grid>
);
};

export default UserMenu;
Loading

0 comments on commit 95499e1

Please sign in to comment.