From 35a4160e91de5fc8bf2e9e29dc7d3dbdb3d721e9 Mon Sep 17 00:00:00 2001 From: sebas Date: Tue, 5 Nov 2024 17:54:53 -0500 Subject: [PATCH] Refactor Snackbar handling by removing SnackbarAlert component, introducing SnackbarContext and ProgressbarContext for improved state management, and updating the modules and components to utilize these new context. --- frontend/src/__test__/SnackBarAlert.test.jsx | 49 ------- .../src/__test__/SnackbarContext.test.jsx | 47 +++++++ frontend/src/components/common/NavBar.jsx | 132 +++++++----------- .../src/components/common/SnackBarAlert.jsx | 46 ------ .../components/context/ProgressbarContext.jsx | 41 ++++++ .../components/context/SnackbarContext.jsx | 41 ++++++ .../pages/EmploymentCertification.jsx | 25 +--- frontend/src/components/pages/EthicalLine.jsx | 36 +---- frontend/src/components/pages/Home.jsx | 63 ++++----- frontend/src/components/pages/Legal.jsx | 23 +-- frontend/src/components/pages/MyPayslips.jsx | 69 +++------ frontend/src/components/pages/Promotions.jsx | 24 +--- frontend/src/components/pages/Quality.jsx | 22 +-- frontend/src/components/pages/RiskEvents.jsx | 29 +--- frontend/src/components/pages/Sgc.jsx | 23 +-- frontend/src/components/pages/Vacancies.jsx | 21 +-- .../components/pages/VacanciesReferred.jsx | 23 +-- .../shared/AddImagesCarouselDialog.jsx | 97 ++++++------- .../src/components/shared/EmblaCarousel.jsx | 20 +-- frontend/src/components/shared/MyAccount.jsx | 126 ++++++++--------- 20 files changed, 369 insertions(+), 588 deletions(-) delete mode 100644 frontend/src/__test__/SnackBarAlert.test.jsx create mode 100644 frontend/src/__test__/SnackbarContext.test.jsx delete mode 100644 frontend/src/components/common/SnackBarAlert.jsx create mode 100644 frontend/src/components/context/ProgressbarContext.jsx create mode 100644 frontend/src/components/context/SnackbarContext.jsx diff --git a/frontend/src/__test__/SnackBarAlert.test.jsx b/frontend/src/__test__/SnackBarAlert.test.jsx deleted file mode 100644 index 2994b74..0000000 --- a/frontend/src/__test__/SnackBarAlert.test.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { render, screen, fireEvent } from '@testing-library/react'; -import SnackbarAlert from '../components/common/SnackBarAlert'; - -describe('SnackbarAlert Component', () => { - test('renders SnackbarAlert with message and severity', () => { - render( - {}} - /> - ); - expect(screen.getByText('Test Message')).toBeInTheDocument(); - expect(screen.getByRole('alert')).toHaveClass( - 'MuiAlert-standardSuccess' - ); - }); - - test('renders SnackbarAlert with action button', () => { - render( - {}} - action={true} - /> - ); - expect(screen.getByText('Test Message')).toBeInTheDocument(); - expect( - screen.getByRole('button', { name: /aceptar/i }) - ).toBeInTheDocument(); - }); - - test('calls closeSnack function when close button is clicked', () => { - const closeSnackMock = vi.fn(); - render( - - ); - fireEvent.click(screen.getByRole('button', { name: /close/i })); - expect(closeSnackMock).toHaveBeenCalledTimes(1); - }); -}); diff --git a/frontend/src/__test__/SnackbarContext.test.jsx b/frontend/src/__test__/SnackbarContext.test.jsx new file mode 100644 index 0000000..d9df3ec --- /dev/null +++ b/frontend/src/__test__/SnackbarContext.test.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { + SnackbarProvider, + useSnackbar, +} from '../components/context/SnackbarContext'; +import '@testing-library/jest-dom'; + +// Test component to use the Snackbar context +const TestComponent = () => { + const { showSnack } = useSnackbar(); + + return ( + + ); +}; + +describe('SnackbarContext', () => { + it('should show and hide the snackbar with the correct message and severity', async () => { + render( + + + + ); + + // Click the button to show the snackbar + fireEvent.click(screen.getByText('Show Snackbar')); + + // Check if the snackbar is displayed with the correct message and severity + expect(await screen.findByText('Test message')).toBeInTheDocument(); + expect(screen.getByRole('alert')).toHaveClass( + 'MuiAlert-standardSuccess' + ); + + // Wait for the snackbar to auto-hide + await waitFor( + () => { + expect( + screen.queryByText('Test message') + ).not.toBeInTheDocument(); + }, + { timeout: 4000 } + ); + }); +}); diff --git a/frontend/src/components/common/NavBar.jsx b/frontend/src/components/common/NavBar.jsx index 6b4d89c..3e82fd0 100644 --- a/frontend/src/components/common/NavBar.jsx +++ b/frontend/src/components/common/NavBar.jsx @@ -3,13 +3,16 @@ import { useState, useEffect, useRef } from 'react'; // Libraries import { useNavigate, useMatch } from 'react-router-dom'; -// Custom Components +// Custom Hooks +import { useProgressbar } from '../context/ProgressbarContext'; // Adjust the path +import { useSnackbar } from '../context/SnackbarContext'; + +// Custom Components/Functions import Goals from '../shared/Goals'; -import SnackbarAlert from './SnackBarAlert'; -import { getApiUrl } from '../../assets/getApi'; import MyAccountDialog from '../shared/MyAccount'; import InactivityDetector from '../shared/InactivityDetector'; import Notifications from '../shared/Notifications'; +import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; // Material-UI @@ -24,8 +27,6 @@ import { Avatar, ListItemIcon, ListItemText, - LinearProgress, - Fade, Dialog, DialogTitle, DialogContent, @@ -41,6 +42,9 @@ import { Alert, } from '@mui/material'; +// MUI Lab +import { LoadingButton } from '@mui/lab'; + // Icons import Logout from '@mui/icons-material/Logout'; import FlagIcon from '@mui/icons-material/Flag'; @@ -58,29 +62,24 @@ import TopicIcon from '@mui/icons-material/Topic'; import NotificationsIcon from '@mui/icons-material/Notifications'; import BeachAccessIcon from '@mui/icons-material/BeachAccess'; import SportsScoreIcon from '@mui/icons-material/SportsScore'; -import TipsAndUpdatesIcon from '@mui/icons-material/TipsAndUpdates'; +import EmailIcon from '@mui/icons-material/Email'; import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism'; // Media import logotipo from '../../images/cyc-logos/logo-navbar.webp'; const Navbar = () => { - const [openCollapse, setOpenCollapse] = useState(false); const [openCollapseEmail, setOpenCollapseEmail] = useState(false); const [anchorEl, setAnchorEl] = useState(null); const [anchorElUtils, setAnchorElUtils] = useState(null); const open = Boolean(anchorEl); const navigate = useNavigate(); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); const openUtils = Boolean(anchorElUtils); const [openDialog, setOpenDialog] = useState(false); const [openAccountDialog, setOpenAccountDialog] = useState(false); const [openCertification, setOpenCertification] = useState(false); const [openCollapseBonuses, setOpenCollapseBonuses] = useState(false); const [checked, setChecked] = useState(false); - const [openPqrs, setOpenPqrs] = useState(false); const cargoItem = localStorage.getItem('cargo'); const isAdvisor = cargoItem && JSON.parse(cargoItem).includes('ASESOR'); const permissions = JSON.parse(localStorage.getItem('permissions')); @@ -92,6 +91,9 @@ const Navbar = () => { const operationalRiskPermission = permissions && permissions.includes('operational_risk.view_events'); const rank = JSON.parse(localStorage.getItem('rango')); + const { isProgressVisible, showProgressbar, hideProgressbar } = + useProgressbar(); + const { showSnack } = useSnackbar(); const servicesPermission = permissions && @@ -219,8 +221,6 @@ const Navbar = () => { getNotifications(); }, [openNotification]); - const handleCloseSnack = () => setOpenSnack(false); - const handleOpenCertification = () => setOpenCertification(true); const handleCloseCertification = () => { @@ -261,12 +261,6 @@ const Navbar = () => { setOpenCollapseEmail(!openCollapseEmail); }; - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const handleLogout = async (inactivity) => { try { const response = await fetch( @@ -302,7 +296,7 @@ const Navbar = () => { }; const sendCertification = async () => { - setOpenCollapse(true); + showProgressbar(); let body = {}; if (checked) { @@ -341,7 +335,7 @@ const Navbar = () => { console.error(error); } } finally { - setOpenCollapse(false); + hideProgressbar(); } }; @@ -359,12 +353,6 @@ const Navbar = () => { showSnack={showSnack} /> ) : null} - { - - + + + Enviar + - - - { ) : null} - {getApiUrl().environment === 'development' ? ( - navigate('/logged/points')}> - - - - - - ) : null} - {getApiUrl().environment === 'development' ? ( - navigate('/logged/pqrs')}> - - - - - - ) : null} - {getApiUrl().environment === 'development' ? ( - - navigate('/logged/coexistence-committee') - } - > - - - - - - ) : null} - - {getApiUrl().environment === 'development' ? ( - navigate('/logged/pqrs')} - > - - - - - - ) : null} - + navigate('/logged/points')}> + + + + + + navigate('/logged/pqrs')}> + + + + + + navigate('/logged/coexistence-committee')} + > + + + + + @@ -765,7 +730,8 @@ const Navbar = () => { ) : null} {permissions && (permissions.includes('users.upload_robinson_list') || - permissions.includes('goals.add_goals')) ? ( + permissions.includes('goals.add_goals') || + permissions.includes('users.upload_points')) ? ( navigate('/logged/upload-files')}> diff --git a/frontend/src/components/common/SnackBarAlert.jsx b/frontend/src/components/common/SnackBarAlert.jsx deleted file mode 100644 index 7ae0b43..0000000 --- a/frontend/src/components/common/SnackBarAlert.jsx +++ /dev/null @@ -1,46 +0,0 @@ -// Material-UI -import { Snackbar, Alert, Button } from '@mui/material'; - -const SnackbarAlert = ({ - message, - severity, - openSnack, - closeSnack, - action, -}) => { - if (!action) { - return ( - - - {message} - - - ); - } else { - return ( - - - Aceptar - - } - > - {message} - - - ); - } -}; - -export default SnackbarAlert; diff --git a/frontend/src/components/context/ProgressbarContext.jsx b/frontend/src/components/context/ProgressbarContext.jsx new file mode 100644 index 0000000..1df35d3 --- /dev/null +++ b/frontend/src/components/context/ProgressbarContext.jsx @@ -0,0 +1,41 @@ +import React, { createContext, useState, useContext } from 'react'; +import { Fade, LinearProgress } from '@mui/material'; + +// Create ProgressBar context +const ProgressbarContext = createContext(); + +// ProgressBarProvider component +export const ProgressbarProvider = ({ children }) => { + const [isProgressVisible, setIsProgressVisible] = useState(false); + + const showProgressbar = () => { + setIsProgressVisible(true); + }; + + const hideProgressbar = () => { + setIsProgressVisible(false); + }; + + return ( + + {children} + + + + + ); +}; + +// Custom hook to use the ProgressBar context +export const useProgressbar = () => useContext(ProgressbarContext); diff --git a/frontend/src/components/context/SnackbarContext.jsx b/frontend/src/components/context/SnackbarContext.jsx new file mode 100644 index 0000000..4894c11 --- /dev/null +++ b/frontend/src/components/context/SnackbarContext.jsx @@ -0,0 +1,41 @@ +import React, { createContext, useContext, useState } from 'react'; +import { Snackbar, Alert } from '@mui/material'; + +// Create the context +const SnackbarContext = createContext(); + +// Snackbar Provider component +export const SnackbarProvider = ({ children }) => { + const [openSnack, setOpenSnack] = useState(false); + const [message, setMessage] = useState(''); + const [severity, setSeverity] = useState('success'); + + const showSnack = (severity, message) => { + setMessage(message); + setSeverity(severity); + setOpenSnack(true); + }; + + const closeSnack = () => { + setOpenSnack(false); + }; + + return ( + + {children} + + + {message} + + + + ); +}; + +// Custom hook to use the Snackbar context +export const useSnackbar = () => useContext(SnackbarContext); diff --git a/frontend/src/components/pages/EmploymentCertification.jsx b/frontend/src/components/pages/EmploymentCertification.jsx index 42a4ebe..2fd4a6c 100644 --- a/frontend/src/components/pages/EmploymentCertification.jsx +++ b/frontend/src/components/pages/EmploymentCertification.jsx @@ -4,7 +4,6 @@ import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; // Custom Components -import SnackbarAlert from '../common/SnackBarAlert'; import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; import { @@ -16,12 +15,15 @@ import { import { Container, Typography, Box } from '@mui/material'; import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +// Custom hooks +import { useSnackbar } from '../context/SnackbarContext'; + export const EmploymentCertification = () => { const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); + const [loading, setLoading] = useState(false); + const { showSnack } = useSnackbar(); + const navigate = useNavigate(); const permissions = JSON.parse(localStorage.getItem('permissions')); @@ -67,14 +69,6 @@ export const EmploymentCertification = () => { getEmploymentCertifications(); }, []); - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - - const handleCloseSnack = () => setOpenSnack(false); - const columns = [ { field: 'cedula', headerName: 'Cedula', width: 100 }, { field: 'position', headerName: 'Cargo', width: 360, editable: false }, @@ -186,13 +180,6 @@ export const EmploymentCertification = () => { > - - ); }; diff --git a/frontend/src/components/pages/EthicalLine.jsx b/frontend/src/components/pages/EthicalLine.jsx index ed95119..3149c85 100644 --- a/frontend/src/components/pages/EthicalLine.jsx +++ b/frontend/src/components/pages/EthicalLine.jsx @@ -5,8 +5,10 @@ import { Formik, Form, useField, Field } from 'formik'; import { useNavigate } from 'react-router-dom'; import * as Yup from 'yup'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom Components -import SnackbarAlert from '../common/SnackBarAlert'; import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; @@ -22,7 +24,6 @@ import { TextField, MenuItem, Button, - LinearProgress, Collapse, Radio, RadioGroup, @@ -81,11 +82,9 @@ const baseInitialValues = { const EthicalLine = () => { const [loadingBar, setLoadingBar] = useState(false); - const [openSnack, setOpenSnack] = useState(false); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); const [collapse, setCollapse] = useState(false); const navigate = useNavigate(); + const { showSnack } = useSnackbar(); const FormikError = ({ name }) => { const [meta] = useField(name); @@ -95,14 +94,6 @@ const EthicalLine = () => { ) : null; }; - const handleCloseSnack = () => setOpenSnack(false); - - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const handleSubmit = async (values) => { let { contact, ...rest } = values; @@ -418,25 +409,6 @@ const EthicalLine = () => { )} - {loadingBar && ( - - - - )} - ); diff --git a/frontend/src/components/pages/Home.jsx b/frontend/src/components/pages/Home.jsx index a35ef68..d7cf669 100644 --- a/frontend/src/components/pages/Home.jsx +++ b/frontend/src/components/pages/Home.jsx @@ -3,10 +3,12 @@ import React, { useEffect, useState } from 'react'; // Custom Components import { getApiUrl } from '../../assets/getApi.js'; import CarouselComponent from '../shared/Carousel'; -import SnackbarAlert from '../common/SnackBarAlert'; import { handleError } from '../../assets/handleError'; import { EmblaCarousel } from '../shared/EmblaCarousel.jsx'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Material-UI import { Typography, Box, Container, useMediaQuery, Card } from '@mui/material'; @@ -19,51 +21,41 @@ import AvatarImage from '../../images/home-carousel/avatar.jpg'; import securityPractices from '../../images/home-carousel/security-practices.png'; import differentiationMatrices from '../../images/home-carousel/differentiation-matrices.png'; import points from '../../images/home-carousel/points.png'; -import water from '../../images/home-carousel/water.png'; import socialMedia from '../../images/home-carousel/social-media.png'; import mapProcess from '../../images/home-carousel/process-map.png'; -import electricityCampaign from '../../images/home-carousel/electricity-campaign.png'; -import passwords from '../../images/home-carousel/password.png'; -import valentine from '../../images/home-carousel/valentine.png'; -import valentine2 from '../../images/home-carousel/valentine-2.png'; -import valentine3 from '../../images/home-carousel/valentine-3.png'; -import halloween from '../../images/home-carousel/halloween-2.png'; +import harassmentPrevention from '../../images/home-carousel/harassment-prevention.png'; +import harassmentPrevention2 from '../../images/home-carousel/harassment-prevention-2.png'; +import harassmentPrevention3 from '../../images/home-carousel/harassment-prevention-3.png'; +import compensationFund from '../../images/home-carousel/compensation-fund.png'; +import clothSize from '../../images/home-carousel/cloth-size.png'; +import halloween from '../../images/home-carousel/halloween.png'; +import noViolenceWomen from '../../images/home-carousel/no-violence-women.png'; const benefits = [{ image: realBenefit2, title: 'Beneficio 2' }]; const homeImages = [ + { image: noViolenceWomen }, { image: halloween }, - { image: valentine }, - { image: valentine2 }, - { image: valentine3 }, - { image: passwords }, - { image: electricityCampaign }, - { image: mapProcess }, + { image: compensationFund }, + { image: clothSize }, { image: points }, - { image: water }, + { image: mapProcess }, + { image: harassmentPrevention }, + { image: harassmentPrevention2 }, + { image: harassmentPrevention3 }, + { image: securityPractices }, { image: socialMedia }, { image: differentiationMatrices }, - { image: securityPractices }, { image: ceroDiscrimination }, ]; const Home = () => { - const [openSnack, setOpenSnack] = useState(false); - const [message, setMessage] = useState(''); - const [severity, setSeverity] = useState('success'); const [todayBirthdays, setTodayBirthdays] = useState([]); const [yesterdayBirthdays, setYesterdayBirthdays] = useState([]); const [tomorrowBirthdays, setTomorrowBirthdays] = useState([]); + const { showSnack } = useSnackbar(); const matches = useMediaQuery('(min-width:1025px)'); - const handleCloseSnack = () => setOpenSnack(false); - - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const fetchImages = async (employees) => { const imagePromises = employees.map(async (employee) => { try { @@ -155,12 +147,12 @@ const Home = () => { return ( <> - {/* @@ -170,8 +162,8 @@ const Home = () => { height={matches ? '648px' : '480px'} width={matches ? '1152px' : '854px'} /> - */} - + {/* { }} > - + */} { /> - - ); }; diff --git a/frontend/src/components/pages/Legal.jsx b/frontend/src/components/pages/Legal.jsx index 865ebde..52df354 100644 --- a/frontend/src/components/pages/Legal.jsx +++ b/frontend/src/components/pages/Legal.jsx @@ -4,8 +4,10 @@ import * as Yup from 'yup'; import { Formik, Form, useField } from 'formik'; import { useNavigate } from 'react-router-dom'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom Components -import SnackbarAlert from '../common/SnackBarAlert'; import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; import { @@ -388,11 +390,9 @@ export const Legal = () => { }; const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); const [details, setDetails] = useState({}); - const [openSnack, setOpenSnack] = useState(false); const [openDialog, setOpenDialog] = useState(false); + const { showSnack } = useSnackbar(); const [openDialogEdit, setOpenDialogEdit] = useState(false); const [disabled, setDisabled] = useState(false); const [inputs, setInputs] = useState(initialInputs); @@ -483,14 +483,6 @@ export const Legal = () => { setDisabled(!disabled); }; - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - - const handleCloseSnack = () => setOpenSnack(false); - const handleDeleteClick = async (id) => { try { const response = await fetch( @@ -772,12 +764,7 @@ export const Legal = () => { > - + { const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); + const { showSnack } = useSnackbar(); const [openDialog, setOpenDialog] = useState(false); const [openCollapse, setOpenCollapse] = useState(false); const [paySlipId, setPaySlipId] = useState(null); - const [disabled, setDisabled] = useState(false); - const [loading, setLoading] = useState(false); const [loadingRows, setLoadingRows] = useState(false); const currentEmail = JSON.parse(localStorage.getItem('email')); const permissions = JSON.parse(localStorage.getItem('permissions')); const cedula = JSON.parse(localStorage.getItem('cedula')); + const { isProgressVisible, showProgressbar, hideProgressbar } = + useProgressbar(); useEffect(() => { window.scrollTo(0, 0); @@ -85,12 +89,6 @@ export const MyPayslips = () => { getPayslips(); }, []); - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const handleCollapse = () => { setOpenCollapse(!openCollapse); }; @@ -100,8 +98,6 @@ export const MyPayslips = () => { setOpenDialog(true); }; - const handleCloseSnack = () => setOpenSnack(false); - const handleCloseDialog = () => { setOpenDialog(false); setOpenCollapse(false); @@ -109,8 +105,7 @@ export const MyPayslips = () => { }; const handleResend = async () => { - setDisabled(true); - setLoading(true); + showProgressbar(); try { const response = await fetch( @@ -126,17 +121,15 @@ export const MyPayslips = () => { if (response.status === 201) { showSnack('success', 'Desprendible reenviado correctamente'); setPaySlipId(null); - setDisabled(false); setOpenDialog(false); setOpenCollapse(false); - setLoading(false); } } catch (error) { if (getApiUrl().environment === 'development') { console.error(error); } - setDisabled(false); - setLoading(false); + } finally { + hideProgressbar(); } }; @@ -218,17 +211,6 @@ export const MyPayslips = () => { return ( <> - - - { - + - - { + const { showSnack } = useSnackbar(); const [yesterdayBirthdays, setYesterdayBirthdays] = useState([]); const [todayBirthdays, setTodayBirthdays] = useState([]); const [tomorrowBirthdays, setTomorrowBirthdays] = useState([]); - const [openSnack, setOpenSnack] = useState(false); - const [message, setMessage] = useState(''); - const [severity, setSeverity] = useState('success'); - - const handleCloseSnack = () => { - setOpenSnack(false); - }; - - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; const fetchImages = async (employees) => { const imagePromises = employees.map(async (employee) => { @@ -169,12 +159,6 @@ const Promotions = () => { width={'100%'} /> - ); diff --git a/frontend/src/components/pages/Quality.jsx b/frontend/src/components/pages/Quality.jsx index 96cb89c..9c0c564 100644 --- a/frontend/src/components/pages/Quality.jsx +++ b/frontend/src/components/pages/Quality.jsx @@ -3,8 +3,10 @@ import { useState, useEffect, useRef } from 'react'; // Libraries import { useNavigate } from 'react-router-dom'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom Components -import SnackbarAlert from '../common/SnackBarAlert'; import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; @@ -69,9 +71,7 @@ const Quality = () => { const [openCollapse, setOpenCollapse] = useState(true); const [fileName, setFileName] = useState(''); const [loading, setLoading] = useState(false); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); + const { showSnack } = useSnackbar(); const [selectedCampaign, setSelectedCampaign] = useState(campaigns[0]); // Set default campaign const callType = useRef(); const navigate = useNavigate(); @@ -96,12 +96,6 @@ const Quality = () => { } }; - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const handleCampaignChange = (event) => { const selectedCampaignValue = event.target.value; const campaign = campaigns.find( @@ -110,8 +104,6 @@ const Quality = () => { setSelectedCampaign(campaign); }; - const handleCloseSnack = () => setOpenSnack(false); - const handleUpload = async () => { setLoading(true); if (selectedFile) { @@ -314,12 +306,6 @@ const Quality = () => { ) : null} - ); diff --git a/frontend/src/components/pages/RiskEvents.jsx b/frontend/src/components/pages/RiskEvents.jsx index 4f48571..ce0059b 100644 --- a/frontend/src/components/pages/RiskEvents.jsx +++ b/frontend/src/components/pages/RiskEvents.jsx @@ -5,9 +5,11 @@ import { useNavigate } from 'react-router-dom'; import { Formik, Form, useField } from 'formik'; import * as Yup from 'yup'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom components import { getApiUrl } from '../../assets/getApi'; -import SnackbarAlert from '../common/SnackBarAlert'; import { handleError } from '../../assets/handleError'; import { CustomNoResultsOverlay, @@ -69,11 +71,9 @@ const validationSchema = Yup.object().shape({ }); export const RiskEvent = () => { + const { showSnack } = useSnackbar(); const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); const [details, setDetails] = useState({}); - const [openSnack, setOpenSnack] = useState(false); const [openDialog, setOpenDialog] = useState(false); const [openDialogEdit, setOpenDialogEdit] = useState(false); const [disabled, setDisabled] = useState(false); @@ -177,14 +177,6 @@ export const RiskEvent = () => { setDisabled(!disabled); }; - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - - const handleCloseSnack = () => setOpenSnack(false); - const handleDeleteClick = async (id) => { try { const response = await fetch( @@ -501,7 +493,6 @@ export const RiskEvent = () => { }, { field: 'event_title', - type: 'text', headerName: 'Evento', width: 100, editable: false, @@ -557,7 +548,6 @@ export const RiskEvent = () => { }, { field: 'description', - type: 'text', headerName: 'Descripción del Evento', width: 100, editable: false, @@ -634,7 +624,6 @@ export const RiskEvent = () => { }, { field: 'reported_by', - type: '', headerName: 'Reportado Por', width: 100, editable: false, @@ -673,21 +662,18 @@ export const RiskEvent = () => { }, { field: 'public_accounts_affected', - type: 'text', headerName: 'Cuentas PUC Afectadas', width: 100, editable: false, }, { field: 'plan', - type: '', headerName: 'Plan', width: 100, editable: false, }, { field: 'learning', - type: '', headerName: 'Aprendizaje', width: 100, editable: false, @@ -787,12 +773,7 @@ export const RiskEvent = () => { > - + { const hiddenFileInput = useRef(null); const [rowModesModel, setRowModesModel] = useState({}); const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); + const { showSnack } = useSnackbar(); const [openDialog, setOpenDialog] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const [selectedFileUpdate, setSelectedFileUpdate] = useState(null); @@ -174,14 +174,6 @@ export const Sgc = () => { }; const handleOpenDialog = () => setOpenDialog(true); - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - - const handleCloseSnack = () => setOpenSnack(false); - const handleEditClick = (id) => () => { setRowModesModel({ ...rowModesModel, @@ -652,12 +644,7 @@ export const Sgc = () => { > - + { const [openVacancy, setOpenVacancy] = useState(false); - const [openSnack, setOpenSnack] = useState(false); - const [message, setMessage] = useState(''); - const [severity, setSeverity] = useState('success'); + const { showSnack } = useSnackbar(); const [vacancyId, setVacancyId] = useState(); const [openCollapse, setOpenCollapse] = useState(false); const [openAddVacancy, setOpenAddVacancy] = useState(false); @@ -162,12 +162,6 @@ const Vacancies = () => { } }; - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - const handleCloseVacancy = () => { setOpenVacancy(false); setOpenCollapse(false); @@ -226,7 +220,6 @@ const Vacancies = () => { const handleOpenAddVacancy = () => setOpenAddVacancy(true); - const handleCloseSnack = () => setOpenSnack(false); const handleOpenCollapse = () => { setOpenCollapse(true); setVacancyDescription( @@ -518,12 +511,6 @@ const Vacancies = () => { - ); }; diff --git a/frontend/src/components/pages/VacanciesReferred.jsx b/frontend/src/components/pages/VacanciesReferred.jsx index cb51565..cfe0d7d 100644 --- a/frontend/src/components/pages/VacanciesReferred.jsx +++ b/frontend/src/components/pages/VacanciesReferred.jsx @@ -3,8 +3,10 @@ import { useState, useEffect } from 'react'; // Libraries import { useNavigate } from 'react-router-dom'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom Components -import SnackbarAlert from '../common/SnackBarAlert'; import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; import { @@ -26,9 +28,7 @@ import { export const VacanciesReferred = () => { const [rows, setRows] = useState([]); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(); - const [openSnack, setOpenSnack] = useState(false); + const { showSnack } = useSnackbar(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const permissions = JSON.parse(localStorage.getItem('permissions')); @@ -70,14 +70,6 @@ export const VacanciesReferred = () => { getVacanciesReferred(); }, []); - const showSnack = (severity, message) => { - setSeverity(severity); - setMessage(message); - setOpenSnack(true); - }; - - const handleCloseSnack = () => setOpenSnack(false); - const CustomToolbar = () => { return ( @@ -168,13 +160,6 @@ export const VacanciesReferred = () => { > - - ); }; diff --git a/frontend/src/components/shared/AddImagesCarouselDialog.jsx b/frontend/src/components/shared/AddImagesCarouselDialog.jsx index bf5d822..2076725 100644 --- a/frontend/src/components/shared/AddImagesCarouselDialog.jsx +++ b/frontend/src/components/shared/AddImagesCarouselDialog.jsx @@ -19,18 +19,22 @@ import { MenuItem, Box, DialogContentText, - LinearProgress, - Fade, FormGroup, FormControlLabel, Checkbox, Collapse, } from '@mui/material'; +// MUI Lab +import { LoadingButton } from '@mui/lab'; + +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; +import { useProgressbar } from '../context/ProgressbarContext'; + // Custom components and assets import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; -import SnackbarAlert from '../common/SnackBarAlert'; registerPlugin( FilePondPluginImageExifOrientation, @@ -46,26 +50,35 @@ const AddImagesCarouselDialog = ({ setImages, }) => { const [image, setImage] = useState([]); - const [openSnack, setOpenSnack] = useState(false); - const [message, setMessage] = useState(''); - const [severity, setSeverity] = useState('success'); - const [loadingBar, setLoadingBar] = useState(false); + const { showSnack } = useSnackbar(); const [openCollapse, setOpenCollapse] = useState(false); + const { isProgressVisible, showProgressbar, hideProgressbar } = + useProgressbar(); - const handleCloseSnack = () => { - setOpenSnack(false); + const handleSubmit = async (event) => { + event.preventDefault(); + showProgressbar(); + const position = event.target.position?.value || ''; + const link = openCollapse ? event.target.link.value : ''; + if (!validateFormData(image)) return; + + const formData = createFormData(image, position, link); + await sendApiRequest(formData); }; - const showSnack = (severity, message) => { - setMessage(message); - setSeverity(severity); - setOpenSnack(true); + const validateFormData = (image) => { + if (image.length === 0) { + showSnack('error', 'Debes añadir una imagen'); + hideProgressbar(); + return false; + } + return true; }; const createFormData = (image, position, link) => { const formData = new FormData(); formData.append('image', image[0]); - formData.append('title', image[0].name); + formData.append('title', image[0]?.name); formData.append('order', position); if (link) { @@ -74,25 +87,13 @@ const AddImagesCarouselDialog = ({ return formData; }; - const validateFormData = (image) => { - if (image.length === 0) { - showSnack('error', 'Debes añadir una imagen'); - setLoadingBar(false); - return false; - } - return true; - }; - const sendApiRequest = async (formData) => { try { - const response = await fetch( - `${getApiUrl().apiUrl}carousel-images/banners/`, - { - method: 'POST', - credentials: 'include', - body: formData, - } - ); + const response = await fetch('http://localhost/', { + method: 'POST', + credentials: 'include', + body: formData, + }); await handleError(response, showSnack); @@ -106,36 +107,17 @@ const AddImagesCarouselDialog = ({ } } finally { setOpenAddDialog(false); - setLoadingBar(false); + hideProgressbar(); } }; - const handleSubmit = async (event) => { - event.preventDefault(); - console.log(event.target.position); - const position = event.target.position.value; - const link = openCollapse ? event.target.link.value : ''; - if (!validateFormData(image)) return; - - const formData = createFormData(image, position, link); - await sendApiRequest(formData); - }; - return ( - - - - setOpenAddDialog(false)} @@ -180,7 +162,6 @@ const AddImagesCarouselDialog = ({ id="position" name="position" select - required label="Posición" variant="outlined" defaultValue={1} @@ -196,6 +177,7 @@ const AddImagesCarouselDialog = ({ - + diff --git a/frontend/src/components/shared/EmblaCarousel.jsx b/frontend/src/components/shared/EmblaCarousel.jsx index 8fdbc27..2bb504a 100644 --- a/frontend/src/components/shared/EmblaCarousel.jsx +++ b/frontend/src/components/shared/EmblaCarousel.jsx @@ -4,11 +4,13 @@ import Autoplay from 'embla-carousel-autoplay'; import { useState, useEffect } from 'react'; import { DotButton, useDotButton } from './EmblaCarouselDotButton'; +// Custom Hooks +import { useSnackbar } from '../context/SnackbarContext'; + // Custom Functions and Components import { getApiUrl } from '../../assets/getApi'; import { handleError } from '../../assets/handleError'; import AddImagesCarouselDialog from './AddImagesCarouselDialog'; -import SnackbarAlert from '../common/SnackBarAlert'; // Icons import DeleteForeverIcon from '@mui/icons-material/DeleteForever'; @@ -83,23 +85,15 @@ const IconButtonsStyle = { }; export function EmblaCarousel() { + const { showSnack } = useSnackbar(); const [images, setImages] = useState([]); const [openAddDialog, setOpenAddDialog] = useState(false); - const [severity, setSeverity] = useState('success'); - const [message, setMessage] = useState(''); - const [openSnack, setOpenSnack] = useState(false); const permissions = JSON.parse(localStorage.getItem('permissions')); useEffect(() => { getCarouselImages(setImages); }, []); - const showSnack = (severity, message) => { - setMessage(message); - setSeverity(severity); - setOpenSnack(true); - }; - const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }, [ Autoplay({ delay: 4000, stopOnInteraction: false }), ]); @@ -109,12 +103,6 @@ export function EmblaCarousel() { return ( - setOpenSnack(false)} - > { - const [openSnack, setOpenSnack] = useState(false); - const [message, setMessage] = useState(''); - const [severity, setSeverity] = useState('success'); + const { showSnack } = useSnackbar(); const [initialValues, setInitialValues] = useState({}); - const [loadingBar, setLoadingBar] = useState(false); - - const handleCloseSnack = () => { - setOpenSnack(false); - }; - - const showSnack = (severity, message) => { - setMessage(message); - setSeverity(severity); - setOpenSnack(true); - }; + const { isProgressVisible, showProgressbar, hideProgressbar } = + useProgressbar(); const getInitialValues = async () => { try { @@ -199,7 +192,7 @@ const MyAccountDialog = ({ open, onClose }) => { }; const handleSave = async (values) => { - setLoadingBar(true); + showProgressbar(); try { const response = await fetch( `${getApiUrl().apiUrl}users/update-profile/`, @@ -225,59 +218,56 @@ const MyAccountDialog = ({ open, onClose }) => { console.error(error); } } finally { - setLoadingBar(false); + hideProgressbar(); } }; return ( - <> - - - - - - -
- - Tu Cuenta - - Completa y actualiza tu información personal - - - - - - - - - -
-
-
- + + +
+ + Tu Cuenta + + Completa y actualiza tu información personal + + + + + + + + + Actualizar + + +
+
+
); };