diff --git a/src/common/components/AlertMessage.jsx b/src/common/components/AlertMessage.jsx index 1f8fdb255..82c1bfb6c 100644 --- a/src/common/components/AlertMessage.jsx +++ b/src/common/components/AlertMessage.jsx @@ -1,30 +1,44 @@ import { Box } from '@chakra-ui/react'; import PropTypes from 'prop-types'; +import { useState, useEffect } from 'react'; import Text from './Text'; import Icon from './Icon'; import useStyle from '../hooks/useStyle'; import Heading from './Heading'; function AlertMessage({ - message, type, iconColor, withoutIcon, style, textStyle, full, textColor, dangerouslySetInnerHTML, title, children, ...rest + message, type, iconColor, withoutIcon, style, textStyle, full, textColor, dangerouslySetInnerHTML, title, children, onClose, ...rest }) { const { fontColor } = useStyle(); const alertColors = { - soft: '#FFF4DC', - warning: '#FFB718', - success: '#25BF6C', - error: '#dc3545', - info: '#00A0E9', + soft: { background: '#FFF4DC' }, + warning: { background: '#ffefcc', borderColor: '#FFB718' }, + success: { background: '#e0ffe8', borderColor: '#00bb2d' }, + error: { background: '#fee8e8', borderColor: '#EB5757' }, + info: { background: '#37c0ff', borderColor: '#DADADA' }, }; + const [visible, setVisible] = useState(true); + + useEffect(() => { + setVisible(true); + }, []); + + const handleClose = () => { + setVisible(false); + if (onClose) onClose(); + }; + + if (!visible) return null; + return (message || children) && ( {!withoutIcon && ( - + )} {children && children} {!children && ( @@ -59,6 +73,9 @@ function AlertMessage({ )} + ); } @@ -75,6 +92,7 @@ AlertMessage.propTypes = { children: PropTypes.node, withoutIcon: PropTypes.bool, iconColor: PropTypes.string, + onClose: PropTypes.func, }; AlertMessage.defaultProps = { @@ -89,6 +107,7 @@ AlertMessage.defaultProps = { children: null, withoutIcon: false, iconColor: '', + onClose: null, }; export default AlertMessage; diff --git a/src/common/components/AttendanceModal/index.jsx b/src/common/components/AttendanceModal/index.jsx index 4c0b28248..57e454712 100644 --- a/src/common/components/AttendanceModal/index.jsx +++ b/src/common/components/AttendanceModal/index.jsx @@ -6,7 +6,7 @@ import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalFooter, ModalBody, Button, Box, NumberInput, NumberInputStepper, NumberDecrementStepper, NumberIncrementStepper, NumberInputField, FormControl, FormLabel, Flex, Grid, useCheckbox, useCheckboxGroup, Avatar, - useColorMode, useToast, Select, ModalCloseButton, + useColorMode, Select, ModalCloseButton, } from '@chakra-ui/react'; import Icon from '../Icon'; import Text from '../Text'; @@ -15,6 +15,7 @@ import ModalInfo from '../../../js_modules/moduleMap/modalInfo'; import useStyle from '../../hooks/useStyle'; import useCohortHandler from '../../hooks/useCohortHandler'; import handlers from '../../handlers'; +import useCustomToast from '../../hooks/useCustomToast'; function AttendanceModal({ title, message, isOpen, onClose, students, @@ -38,7 +39,7 @@ function AttendanceModal({ const [openAttendanceTakenWarn, setOpenAttendanceTakenWarn] = useState(false); const [attendanceList, setAttendanceList] = useState({}); const { colorMode } = useColorMode(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'attendance-report-apply-modules ' }); const { lightColor, borderColor } = useStyle(); @@ -58,7 +59,7 @@ function AttendanceModal({ setAttendanceList(data); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-getting-previous-attendance'), status: 'error', @@ -121,16 +122,16 @@ function AttendanceModal({ handlers.saveCohortAttendancy({ cohortSlug: cohortSession.slug, students, checked, currentModule }) .then((data) => { setAttendanceList(data); - toast({ + createToast({ position: 'top', title: t('alert-message:attendancy-reported'), status: 'success', - duration: 9000, + duration: 900, isClosable: true, }); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:attendancy-report-error'), status: 'error', @@ -156,7 +157,7 @@ function AttendanceModal({ }); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-updating-day-and-modules'), status: 'error', @@ -168,7 +169,7 @@ function AttendanceModal({ }) .finally(() => setIsLoading(false)); } else { - toast({ + createToast({ position: 'top', title: t('alert-message:error-updating-day-and-modules'), status: 'error', diff --git a/src/common/components/CodeViewer.jsx b/src/common/components/CodeViewer.jsx index a4d329c98..2885582dc 100644 --- a/src/common/components/CodeViewer.jsx +++ b/src/common/components/CodeViewer.jsx @@ -12,7 +12,6 @@ import { TabIndicator, Collapse, Tooltip, - useToast, CircularProgress, } from '@chakra-ui/react'; import { useRouter } from 'next/router'; @@ -26,6 +25,7 @@ import useAuth from '../hooks/useAuth'; import useStyle from '../hooks/useStyle'; import Text from './Text'; import Icon from './Icon'; +import useCustomToast from '../hooks/useCustomToast'; const notExecutables = ['css', 'shell', 'windows', 'mac', 'linux']; @@ -66,7 +66,7 @@ function CodeViewer({ languagesData, allowNotLogged, fileContext, ...rest }) { const { hexColor } = useStyle(); const { t } = useTranslation('code-viewer'); const { isAuthenticated } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'code-viewer-error-string' }); const [initialTouchY, setInitialTouchY] = useState(null); const [tabIndex, setTabIndex] = useState(0); const [showModal, setShowModal] = useState(false); @@ -190,7 +190,7 @@ function CodeViewer({ languagesData, allowNotLogged, fileContext, ...rest }) { currLanguage, ...languages.slice(tabIndex + 1), ]); - toast({ + createToast({ position: 'top', title: typeof e === 'string' ? e : t('error'), status: 'error', diff --git a/src/common/components/CohortSideBar.jsx b/src/common/components/CohortSideBar.jsx index 22d7afe56..974ad8913 100644 --- a/src/common/components/CohortSideBar.jsx +++ b/src/common/components/CohortSideBar.jsx @@ -5,7 +5,7 @@ import { memo, useState, useEffect } from 'react'; // import { w3cwebsocket as W3CWebSocket } from 'websocket'; import { Box, Heading, Divider, Grid, Tabs, - TabList, Tab, TabPanels, TabPanel, useToast, AvatarGroup, useMediaQuery, Flex, + TabList, Tab, TabPanels, TabPanel, AvatarGroup, useMediaQuery, Flex, } from '@chakra-ui/react'; import PropTypes from 'prop-types'; import { format, differenceInWeeks } from 'date-fns'; @@ -23,6 +23,7 @@ import useStyle from '../hooks/useStyle'; import useCohortHandler from '../hooks/useCohortHandler'; import useProgramList from '../store/actions/programListAction'; import { isWindow } from '../../utils'; +import useCustomToast from '../hooks/useCustomToast'; function ProfilesSection({ title, paginationProps, isTeacherVersion, setAlumniGeeksList, profiles, wrapped, teacher, withoutPopover, showButton, @@ -221,7 +222,7 @@ function CohortSideBar({ }) { const { t } = useTranslation('dashboard'); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'cohort-side-bar-fetching-alumni-error' }); const { slug } = router.query; const [alumniGeeksList, setAlumniGeeksList] = useState({}); const [activeStudentsLoading, setActiveStudentsLoading] = useState(true); @@ -278,7 +279,7 @@ function CohortSideBar({ ), }); }).catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-alumni-geeks'), status: 'error', diff --git a/src/common/components/ConnectGithubRigobot.jsx b/src/common/components/ConnectGithubRigobot.jsx index d1a37b964..f8ac2b619 100644 --- a/src/common/components/ConnectGithubRigobot.jsx +++ b/src/common/components/ConnectGithubRigobot.jsx @@ -3,7 +3,7 @@ import useTranslation from 'next-translate/useTranslation'; import { Box, Button, Heading, InputGroup, InputLeftAddon, Modal, ModalBody, ModalCloseButton, ModalContent, - ModalHeader, ModalOverlay, Stack, Text, Tooltip, useToast, + ModalHeader, ModalOverlay, Stack, Text, Tooltip, } from '@chakra-ui/react'; import { useState } from 'react'; import { useRouter } from 'next/router'; @@ -13,12 +13,13 @@ import bc from '../services/breathecode'; import useAuth from '../hooks/useAuth'; import Icon from './Icon'; import useStyle from '../hooks/useStyle'; +import useCustomToast from '../hooks/useCustomToast'; function ConnectGithubRigobot({ ...rest }) { const { t } = useTranslation('profile'); const { user, isAuthenticatedWithRigobot, conntectToRigobot } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'github-account-removed-error' }); const router = useRouter(); const [modalIsOpen, setModalIsOpen] = useState(false); @@ -165,7 +166,7 @@ function ConnectGithubRigobot({ ...rest }) { setTimeout(() => { router.reload(); }, 1000); - toast({ + createToast({ position: 'top', title: t('alert-message:any-removed', { any: 'GitHub' }), description: t('alert-message:github-account-removed'), @@ -175,7 +176,7 @@ function ConnectGithubRigobot({ ...rest }) { }); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:something-went-wrong'), description: t('alert-message:error-removing-github'), diff --git a/src/common/components/DirectAccessModal.jsx b/src/common/components/DirectAccessModal.jsx index 515b3a72b..9d5bd8204 100644 --- a/src/common/components/DirectAccessModal.jsx +++ b/src/common/components/DirectAccessModal.jsx @@ -1,4 +1,4 @@ -import { Box, Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay, Text, useToast } from '@chakra-ui/react'; +import { Box, Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay, Text } from '@chakra-ui/react'; import { Form, Formik } from 'formik'; import * as Yup from 'yup'; import useTranslation from 'next-translate/useTranslation'; @@ -12,6 +12,7 @@ import Heading from './Heading'; import { setStorageItem, toCapitalize } from '../../utils'; import { BREATHECODE_HOST } from '../../utils/variables'; import { log } from '../../utils/logging'; +import useCustomToast from '../hooks/useCustomToast'; function DirectAccessModal({ title, modalIsOpen }) { const { t } = useTranslation('profile'); @@ -22,7 +23,7 @@ function DirectAccessModal({ title, modalIsOpen }) { const router = useRouter(); const locale = router?.locale; // const technology = router?.query?.technology || 'Python'; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'email-subscribed' }); const [formProps, setFormProps] = useState({ first_name: '', @@ -62,7 +63,7 @@ function DirectAccessModal({ title, modalIsOpen }) { router.push('/thank-you'); } if (resp.status >= 400) { - toast({ + createToast({ position: 'top', title: t('alert-message:email-already-subscribed'), status: 'warning', diff --git a/src/common/components/FinalProject/Form.jsx b/src/common/components/FinalProject/Form.jsx index 51a82914b..8f9a98272 100644 --- a/src/common/components/FinalProject/Form.jsx +++ b/src/common/components/FinalProject/Form.jsx @@ -1,4 +1,4 @@ -import { Button, Flex, useToast, Box, Image } from '@chakra-ui/react'; +import { Button, Flex, Box, Image } from '@chakra-ui/react'; import { Form, Formik } from 'formik'; import PropTypes from 'prop-types'; import useTranslation from 'next-translate/useTranslation'; @@ -13,13 +13,14 @@ import useStyle from '../../hooks/useStyle'; import { isNumber } from '../../../utils'; import useFinalProjectProps from '../../store/actions/finalProjectAction'; import Icon from '../Icon'; +import useCustomToast from '../../hooks/useCustomToast'; function FinalProjectForm({ cohortData, studentsData, handleClose, defaultValues, refreshFinalProject }) { const { t } = useTranslation('final-project'); const [students, setStudents] = useState(studentsData); const [fileProps, setFileProps] = useState([]); const cohortSlug = cohortData?.slug || ''; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'final-project-updating-and-wrong' }); const cohortAcademy = cohortData?.academy?.id || 4; const { finalProjectData, setFinalProjectData } = useFinalProjectProps(); const { fontColor, backgroundColor } = useStyle(); @@ -94,31 +95,34 @@ function FinalProjectForm({ cohortData, studentsData, handleClose, defaultValues if (Array.isArray(data)) { setFinalProjectData(data[0]); refreshFinalProject(); - toast({ + createToast({ position: 'top', title: 'Success', description: 'Your final project has been updated', status: 'success', duration: 5000, + isClosable: true, }); } else { - toast({ + createToast({ position: 'top', title: 'Error', description: data.detail || 'Something went wrong updating your final project', status: 'error', duration: 5000, + isClosable: true, }); } handleClose(); }) .catch(() => { - toast({ + createToast({ position: 'top', title: 'Error', description: 'Something went wrong submiting your final project', status: 'error', duration: 5000, + isClosable: true, }); }); @@ -139,31 +143,34 @@ function FinalProjectForm({ cohortData, studentsData, handleClose, defaultValues .then((res) => { if (res) { setFinalProjectData(res.data[0]); - toast({ + createToast({ position: 'top', title: 'Success', description: 'Your final project has been sended', status: 'success', duration: 5000, + isClosable: true, }); handleClose(); } else { - toast({ + createToast({ position: 'top', title: 'Error', description: 'Something went wrong submiting your final project', status: 'error', duration: 5000, + isClosable: true, }); } }) .catch(() => { - toast({ + createToast({ position: 'top', title: 'Error', description: 'Something went wrong submiting your final project', status: 'error', duration: 5000, + isClosable: true, }); }); diff --git a/src/common/components/Forms/LogIn.jsx b/src/common/components/Forms/LogIn.jsx index 982abb5da..0fd53ab1c 100644 --- a/src/common/components/Forms/LogIn.jsx +++ b/src/common/components/Forms/LogIn.jsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; import useTranslation from 'next-translate/useTranslation'; import { Button, FormControl, Stack, Text, Box, Input, FormErrorMessage, - FormLabel, useToast, Link, Spacer, Flex, InputRightElement, InputGroup, + FormLabel, Link, Spacer, Flex, InputRightElement, InputGroup, } from '@chakra-ui/react'; import { Form, Formik, Field } from 'formik'; import { reportDatalayer } from '../../../utils/requests'; @@ -14,12 +14,13 @@ import useAuth from '../../hooks/useAuth'; import useStyle from '../../hooks/useStyle'; import { BREATHECODE_HOST } from '../../../utils/variables'; import { getBrowserInfo } from '../../../utils'; +import useCustomToast from '../../hooks/useCustomToast'; function LogIn({ hideLabel, actionfontSize, callBack, disableRedirect }) { const { t } = useTranslation('login'); const [showPSW, setShowPSW] = useState(false); const { login } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'welcome-account-not-found' }); // const router = useRouter(); const [curUrl, setUrl] = useState(''); useEffect(() => setUrl(typeof window !== 'undefined' ? window.location.href : ''), []); @@ -41,7 +42,7 @@ function LogIn({ hideLabel, actionfontSize, callBack, disableRedirect }) { actions.setSubmitting(false); callBack(); if (data.status === 200) { - toast({ + createToast({ position: 'top', title: t('alert-message:welcome'), status: 'success', @@ -52,7 +53,7 @@ function LogIn({ hideLabel, actionfontSize, callBack, disableRedirect }) { }) .catch(() => { actions.setSubmitting(false); - toast({ + createToast({ position: 'top', title: t('alert-message:account-not-found'), // description: error.message, diff --git a/src/common/components/Forms/Register.jsx b/src/common/components/Forms/Register.jsx index cbc89da09..5cffde84f 100644 --- a/src/common/components/Forms/Register.jsx +++ b/src/common/components/Forms/Register.jsx @@ -8,7 +8,6 @@ import { FormErrorMessage, Box, Avatar, - useToast, Checkbox, // InputRightElement, } from '@chakra-ui/react'; @@ -27,6 +26,7 @@ import bc from '../../services/breathecode'; import useSession from '../../hooks/useSession'; import useSubscribeToPlan from '../../hooks/useSubscribeToPlan'; import { BASE_PLAN, BREATHECODE_HOST } from '../../../utils/variables'; +import useCustomToast from '../../hooks/useCustomToast'; function Register({ setIsLoggedFromRegister }) { const { userSession } = useSession(); @@ -36,7 +36,7 @@ function Register({ setIsLoggedFromRegister }) { const [verifyEmailProps, setVerifyEmailProps] = useState({}); const [isChecked, setIsChecked] = useState(false); const accessToken = getStorageItem('accessToken'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'email-alert-message-sent-to' }); // const [showPSW, setShowPSW] = useState(false); // const [showRepeatPSW, setShowRepeatPSW] = useState(false); @@ -107,7 +107,7 @@ function Register({ setIsLoggedFromRegister }) { .then((resp) => { const data = resp?.data; if (data === undefined) { - toast({ + createToast({ position: 'top', status: 'info', title: t('signup:alert-message.email-already-sent'), @@ -115,7 +115,7 @@ function Register({ setIsLoggedFromRegister }) { duration: 6000, }); } else { - toast({ + createToast({ position: 'top', status: 'success', title: t('signup:alert-message.email-sent-to', { email: data?.email }), @@ -165,7 +165,7 @@ function Register({ setIsLoggedFromRegister }) { setShowAlreadyMember(true); } if (resp?.status >= 400) { - toast({ + createToast({ position: 'top', title: data?.detail, status: 'error', diff --git a/src/common/components/Forms/Signup.jsx b/src/common/components/Forms/Signup.jsx index 6f02d9082..764b061fe 100644 --- a/src/common/components/Forms/Signup.jsx +++ b/src/common/components/Forms/Signup.jsx @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import * as Yup from 'yup'; import { - Avatar, Box, Button, Checkbox, useToast, + Avatar, Box, Button, Checkbox, Spinner, InputGroup, InputRightElement, @@ -26,6 +26,7 @@ import { reportDatalayer } from '../../../utils/requests'; import useSignup from '../../store/actions/signupAction'; import ModalInfo from '../../../js_modules/moduleMap/modalInfo'; import bc from '../../services/breathecode'; +import useCustomToast from '../../hooks/useCustomToast'; function SignupForm({ planSlug, courseChoosed, showVerifyEmail, subscribeValues, buttonStyles, @@ -63,7 +64,7 @@ function SignupForm({ state, } = useSignup(); const { dateProps } = state; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'signup-error-warning-email' }); const router = useRouter(); const { syllabus } = router.query; @@ -118,7 +119,7 @@ function SignupForm({ if (data.silent_code === SILENT_CODE.USER_EXISTS) { setShowAlreadyMember(true); } else if (resp?.status >= 400 && data.silent_code !== SILENT_CODE.USER_EXISTS) { - toast({ + createToast({ position: 'top', title: data?.detail, status: 'error', @@ -178,7 +179,7 @@ function SignupForm({ } if (resp.status >= 400 && data?.phone) { - toast({ + createToast({ position: 'top', title: data?.phone[0], status: 'warning', @@ -190,7 +191,7 @@ function SignupForm({ } catch (e) { console.log(e); actions.setSubmitting(false); - toast({ + createToast({ position: 'top', title: e.message, status: 'error', @@ -414,7 +415,7 @@ function SignupForm({ .then((resp) => { const data = resp?.data; if (data === undefined) { - toast({ + createToast({ position: 'top', status: 'info', title: t('signup:alert-message.email-already-sent'), @@ -422,7 +423,7 @@ function SignupForm({ duration: 6000, }); } else { - toast({ + createToast({ position: 'top', status: 'success', title: t('signup:alert-message.email-sent-to', { email: data?.email }), diff --git a/src/common/components/PopoverTaskHandler.jsx b/src/common/components/PopoverTaskHandler.jsx index ce7683607..47bf02c11 100644 --- a/src/common/components/PopoverTaskHandler.jsx +++ b/src/common/components/PopoverTaskHandler.jsx @@ -1,6 +1,6 @@ /* eslint-disable react/prop-types */ /* eslint-disable no-unused-vars */ -import { Box, PopoverArrow, Text, Checkbox, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, Button, FormErrorMessage, FormControl, Input, useColorModeValue, useToast, Popover, PopoverTrigger, Tooltip, useFormControlStyles } from '@chakra-ui/react'; +import { Box, PopoverArrow, Text, Checkbox, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, Button, FormErrorMessage, FormControl, Input, useColorModeValue, Popover, PopoverTrigger, Tooltip, useFormControlStyles } from '@chakra-ui/react'; import * as Yup from 'yup'; import { Field, Form, Formik } from 'formik'; import PropTypes from 'prop-types'; @@ -14,6 +14,7 @@ import Icon from './Icon'; import useStyle from '../hooks/useStyle'; import useCohortHandler from '../hooks/useCohortHandler'; import { formatBytes } from '../../utils'; +import useCustomToast from '../hooks/useCustomToast'; export function textByTaskStatus(currentTask, isGuidedExperience, hasPendingSubtask) { const { t } = useTranslation('dashboard'); @@ -139,7 +140,7 @@ function PopoverCustomContent({ const fileInputRef = useRef(); const fileContainerRef = useRef(null); const commonInputActiveColor = useColorModeValue('gray.800', 'gray.350'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'files-uploaded-wrong' }); const deliveryFormatExists = typeof currentAssetData?.delivery_formats === 'string'; const noDeliveryFormat = deliveryFormatExists && currentAssetData?.delivery_formats.includes('no_delivery'); @@ -217,7 +218,7 @@ function PopoverCustomContent({ githubUrl: respData?.url, taskStatus: 'DONE', }); - toast({ + createToast({ position: 'top', title: t('alert-message:files-uploaded'), status: 'success', @@ -227,7 +228,7 @@ function PopoverCustomContent({ closeSettings(); } else { setIsUploading(false); - toast({ + createToast({ position: 'top', title: t('alert-message:something-went-wrong-with', { property: 'Files' }), status: 'error', diff --git a/src/common/components/ProfileForm.jsx b/src/common/components/ProfileForm.jsx index a8e1a1fd5..f430013b7 100644 --- a/src/common/components/ProfileForm.jsx +++ b/src/common/components/ProfileForm.jsx @@ -1,7 +1,7 @@ import useTranslation from 'next-translate/useTranslation'; import { Box, Button, FormControl, FormErrorMessage, FormLabel, Input, - Stack, useToast, + Stack, } from '@chakra-ui/react'; import { Field, Form, Formik } from 'formik'; import { memo, useEffect, useState } from 'react'; @@ -11,11 +11,12 @@ import bc from '../services/breathecode'; import useAuth from '../hooks/useAuth'; import ConnectGithubRigobot from './ConnectGithubRigobot'; import useStyle from '../hooks/useStyle'; +import useCustomToast from '../hooks/useCustomToast'; function ProfileForm() { const { t } = useTranslation('profile'); const { user, updateProfile } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'profile-update-form' }); const [userInfo, setUserInfo] = useState(null); const [defaultUserInfo, setDefaultUserInfo] = useState(null); @@ -49,7 +50,7 @@ function ProfileForm() { actions.setSubmitting(true); bc.auth().updateProfile(values) .then(({ data }) => { - toast({ + createToast({ position: 'top', title: t('profile:profile-updated'), status: 'success', @@ -65,13 +66,14 @@ function ProfileForm() { }); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('profile:update-failed'), // description: err.message, status: 'error', duration: 9000, isClosable: true, + }); }) .finally(() => { diff --git a/src/common/components/ReviewModal/CodeReview.jsx b/src/common/components/ReviewModal/CodeReview.jsx index 3df150336..22297ef6d 100644 --- a/src/common/components/ReviewModal/CodeReview.jsx +++ b/src/common/components/ReviewModal/CodeReview.jsx @@ -1,4 +1,4 @@ -import { Box, Button, Divider, Flex, Link, Textarea, useToast } from '@chakra-ui/react'; +import { Box, Button, Divider, Flex, Link, Textarea } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import dynamic from 'next/dynamic'; import PropTypes from 'prop-types'; @@ -15,6 +15,7 @@ import MarkDownParser from '../MarkDownParser'; import { reportDatalayer } from '../../../utils/requests'; import { getBrowserInfo } from '../../../utils'; import useAuth from '../../hooks/useAuth'; +import useCustomToast from '../../hooks/useCustomToast'; const MarkdownEditor = dynamic( () => import('@uiw/react-markdown-editor').then((mod) => mod.default), @@ -39,7 +40,7 @@ function CodeReview({ isExternal, onClose, disableRate, isStudent, handleResetFl comment: '', isSubmitting: false, }); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'code-review-error' }); const { hexColor } = useStyle(); const [reviewRateData, setReviewRateData] = useState({ status: null, @@ -167,7 +168,7 @@ function CodeReview({ isExternal, onClose, disableRate, isStudent, handleResetFl } }) .catch((error) => { - toast({ + createToast({ title: t('alert-message:error-creating-code-review'), description: error?.message, status: 'error', diff --git a/src/common/components/ReviewModal/DeliverModalContent.jsx b/src/common/components/ReviewModal/DeliverModalContent.jsx index 740376934..1cce8e97f 100644 --- a/src/common/components/ReviewModal/DeliverModalContent.jsx +++ b/src/common/components/ReviewModal/DeliverModalContent.jsx @@ -14,7 +14,6 @@ import { ModalHeader, ModalOverlay, Text, - useToast, useColorModeValue, } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; @@ -22,6 +21,7 @@ import PropTypes from 'prop-types'; import bc from '../../services/breathecode'; import useStyle from '../../hooks/useStyle'; import Icon from '../Icon'; +import useCustomToast from '../../hooks/useCustomToast'; function DeliverModalContent({ isStudent, @@ -40,7 +40,7 @@ function DeliverModalContent({ const { t } = useTranslation('assignments'); const { modal, borderColor2, featuredColor, hexColor } = useStyle(); const [openIgnoreTask, setOpenIgnoreTask] = useState(false); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: ' review-assignment-task-error' }); const [copied, setCopied] = useState(false); const textAreaRef = useRef(null); const fullName = `${currentTask?.user?.first_name} ${currentTask?.user?.last_name}`; @@ -174,7 +174,7 @@ function DeliverModalContent({ revision_status: taskIsIgnored ? 'PENDING' : 'IGNORED', }) .then(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:review-assignment-ignored-task'), status: 'success', @@ -191,7 +191,7 @@ function DeliverModalContent({ }) .catch((e) => { console.log(e); - toast({ + createToast({ position: 'top', title: t('alert-message:review-assignment-error'), status: 'error', diff --git a/src/common/components/ReviewModal/index.jsx b/src/common/components/ReviewModal/index.jsx index 27df26be6..d9c875560 100644 --- a/src/common/components/ReviewModal/index.jsx +++ b/src/common/components/ReviewModal/index.jsx @@ -1,7 +1,7 @@ /* eslint-disable react/prop-types */ import PropTypes from 'prop-types'; import { useEffect, useState } from 'react'; -import { Box, Button, Flex, Link, Textarea, useToast } from '@chakra-ui/react'; +import { Box, Button, Flex, Link, Textarea } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { format } from 'date-fns'; import SimpleModal from '../SimpleModal'; @@ -24,6 +24,7 @@ import useAuth from '../../hooks/useAuth'; import { error } from '../../../utils/logging'; import { reportDatalayer } from '../../../utils/requests'; import { getBrowserInfo } from '../../../utils'; +import useCustomToast from '../../hooks/useCustomToast'; export const stages = { initial: 'initial', @@ -46,7 +47,7 @@ function ReviewModal({ isExternal, externalFiles, isOpen, isStudent, externalDat projectLink, changeStatusAssignment, disableRate, disableLiking, acceptTC, handleAcceptTC, ...rest }) { const { t } = useTranslation('assignments'); const { isAuthenticated, isAuthenticatedWithRigobot, user } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: ' review-status-code-revisions' }); const [selectedText, setSelectedText] = useState(''); const [loaders, setLoaders] = useState({ isFetchingCommitFiles: false, @@ -203,7 +204,7 @@ function ReviewModal({ isExternal, externalFiles, isOpen, isStudent, externalDat my_revisions: data.filter((revision) => revision?.reviewer?.username === user?.email), })); } else { - toast({ + createToast({ title: t('alert-message:something-went-wrong'), description: `Cannot get code revisions: ${data?.detail}`, status: 'error', @@ -307,7 +308,7 @@ function ReviewModal({ isExternal, externalFiles, isOpen, isStudent, externalDat description: comment, }) .then(() => { - toast({ + createToast({ position: 'top', title: alertStatus[reviewStatus], status: 'success', @@ -326,7 +327,7 @@ function ReviewModal({ isExternal, externalFiles, isOpen, isStudent, externalDat onClose(); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:review-assignment-error'), status: 'error', diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 6d2e4c611..cef9b8b71 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -1,5 +1,5 @@ /* eslint-disable react/prop-types */ -import { Avatar, AvatarGroup, Box, Button, Input, InputGroup, InputRightElement, useColorModeValue, useToast } from '@chakra-ui/react'; +import { Avatar, AvatarGroup, Box, Button, Input, InputGroup, InputRightElement, useColorModeValue } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import PropTypes from 'prop-types'; @@ -20,6 +20,7 @@ import { validatePlanExistence } from '../../handlers/subscriptions'; import { getStorageItem, getBrowserInfo } from '../../../utils'; import { reportDatalayer } from '../../../utils/requests'; import { BREATHECODE_HOST } from '../../../utils/variables'; +import useCustomToast from '../../hooks/useCustomToast'; function NoConsumablesCard({ t, setMentoryProps, handleGetMoreMentorships, mentoryProps, subscriptionData, disableBackButton = false, ...rest }) { return ( @@ -113,7 +114,7 @@ function MentoringConsumables({ const [shouldHandleService, setShouldHandleService] = useState(true); const router = useRouter(); const { slug } = router.query; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'finding-mentor-error-service' }); const mentorshipBalance = consumableOfService?.balance?.unit; const currentBalance = Number(mentorshipBalance && mentorshipBalance); @@ -186,7 +187,7 @@ function MentoringConsumables({ manageMentorsData(service, res.data); } } catch (e) { - toast({ + createToast({ position: 'top', title: 'Error', description: t('alert-message:error-finding-mentors'), @@ -202,7 +203,7 @@ function MentoringConsumables({ const getServicesWithMentor = (mentor) => servicesFiltered.filter((service) => mentor.services.some((mentServ) => mentServ.slug === service.slug)); const showErrorToast = () => { - toast({ + createToast({ position: 'top', title: 'Error', description: `${t('supportSideBar.mentor-not-found')} "${queryMentor}"`, @@ -243,7 +244,7 @@ function MentoringConsumables({ const serviceFound = servicesWithMentorsAvailable.find((service) => service.slug === queryService); if (!serviceFound && notifyError) { - toast({ + createToast({ position: 'top', title: 'Error', description: `${t('supportSideBar.service-not-found')} "${queryService}" ${queryMentor ? `${t('common:word-connector.for')} "${queryMentor}"` : ''}`, diff --git a/src/common/components/SupportSidebar/MentoringFree.jsx b/src/common/components/SupportSidebar/MentoringFree.jsx index ba604e9d1..775efcc48 100644 --- a/src/common/components/SupportSidebar/MentoringFree.jsx +++ b/src/common/components/SupportSidebar/MentoringFree.jsx @@ -1,5 +1,5 @@ /* eslint-disable react/prop-types */ -import { Avatar, AvatarGroup, Box, Button, Image, Input, InputGroup, InputRightElement, useColorModeValue, useToast } from '@chakra-ui/react'; +import { Avatar, AvatarGroup, Box, Button, Image, Input, InputGroup, InputRightElement, useColorModeValue } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import PropTypes from 'prop-types'; @@ -13,6 +13,7 @@ import bc from '../../services/breathecode'; import { AvatarSkeletonWrapped } from '../Skeleton'; import useOnline from '../../hooks/useOnline'; import AvatarUser from '../../../js_modules/cohortSidebar/avatarUser'; +import useCustomToast from '../../hooks/useCustomToast'; function ProfilesSection({ profiles, @@ -55,7 +56,7 @@ function MentoringFree({ const { borderColor, lightColor, hexColor } = useStyle(); const [existsMentors, setExistsMentors] = useState(true); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'finding-mentors-error' }); const { slug } = router.query; useEffect(() => { @@ -89,7 +90,7 @@ function MentoringFree({ manageMentorsData(service, res.data); } } catch (e) { - toast({ + createToast({ position: 'top', title: 'Error', description: t('alert-message:error-finding-mentors'), diff --git a/src/common/components/SupportSidebar/index.jsx b/src/common/components/SupportSidebar/index.jsx index 678088533..384a11111 100644 --- a/src/common/components/SupportSidebar/index.jsx +++ b/src/common/components/SupportSidebar/index.jsx @@ -1,16 +1,14 @@ import { useEffect, memo, useState } from 'react'; -import { - useToast, -} from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import PropTypes from 'prop-types'; import bc from '../../services/breathecode'; // import { usePersistent } from '../../hooks/usePersistent'; import Mentoring from './Mentoring'; +import useCustomToast from '../../hooks/useCustomToast'; function SupportSidebar({ allCohorts, allSyllabus, services, subscriptions, subscriptionData }) { const { t } = useTranslation(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'mentorship-error' }); const [programServices, setProgramServices] = useState({ list: [], isFetching: true, @@ -39,7 +37,7 @@ function SupportSidebar({ allCohorts, allSyllabus, services, subscriptions, subs }); } }).catch(() => { - toast({ + createToast({ position: 'top', title: 'Error', description: t('alert-message:error-mentorship-service'), diff --git a/src/common/components/UndoApprovalModal.jsx b/src/common/components/UndoApprovalModal.jsx index c34174062..d72bf000f 100644 --- a/src/common/components/UndoApprovalModal.jsx +++ b/src/common/components/UndoApprovalModal.jsx @@ -1,17 +1,18 @@ -import { Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useColorModeValue, useToast } from '@chakra-ui/react'; +import { Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useColorModeValue } from '@chakra-ui/react'; import PropTypes from 'prop-types'; import useTranslation from 'next-translate/useTranslation'; import { useState } from 'react'; import useStyle from '../hooks/useStyle'; import Text from './Text'; import bc from '../services/breathecode'; +import useCustomToast from '../hooks/useCustomToast'; function UndoApprovalModal({ isOpen, currentTask, onSuccess, onClose, updpateAssignment }) { const { modal, borderColor2 } = useStyle(); const [isRequesting, setIsRequesting] = useState(false); const labelColor = useColorModeValue('gray.600', 'gray.200'); const { t } = useTranslation('assignments'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: ' review-assignment-updated-and-error' }); const fullName = `${currentTask?.user?.first_name} ${currentTask?.user?.last_name}`; const taskIsIgnored = currentTask?.revision_status === 'IGNORED'; @@ -51,7 +52,7 @@ function UndoApprovalModal({ isOpen, currentTask, onSuccess, onClose, updpateAss }); onSuccess(); onClose(); - toast({ + createToast({ position: 'top', title: t('alert-message:review-assignment-updated'), status: 'success', @@ -61,7 +62,7 @@ function UndoApprovalModal({ isOpen, currentTask, onSuccess, onClose, updpateAss }) .catch((e) => { console.log(e); - toast({ + createToast({ position: 'top', title: t('alert-message:review-assignment-error'), status: 'error', diff --git a/src/common/context/AuthContext.jsx b/src/common/context/AuthContext.jsx index 8eea118c4..5b26701a1 100644 --- a/src/common/context/AuthContext.jsx +++ b/src/common/context/AuthContext.jsx @@ -2,7 +2,7 @@ import React, { createContext, useEffect, useReducer, useState } from 'react'; import PropTypes from 'prop-types'; import { useRouter } from 'next/router'; import useTranslation from 'next-translate/useTranslation'; -import { Avatar, Box, useToast } from '@chakra-ui/react'; +import { Avatar, Box } from '@chakra-ui/react'; import bc from '../services/breathecode'; import { getQueryString, isWindow, removeStorageItem, removeURLParameter, getBrowserInfo } from '../../utils'; import { reportDatalayer, getPrismicPages } from '../../utils/requests'; @@ -16,6 +16,7 @@ import Text from '../components/Text'; import { SILENT_CODE } from '../../lib/types'; import { warn } from '../../utils/logging'; import { generateUserContext } from '../../utils/rigobotContext'; +import useCustomToast from '../hooks/useCustomToast'; const initialState = { isLoading: true, @@ -124,7 +125,7 @@ export const AuthContext = createContext({ function AuthProvider({ children, pageProps }) { const router = useRouter(); const { t, lang } = useTranslation('footer'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'auth-context-email-sent' }); const { rigo, isRigoInitialized } = useRigo(); const queryCoupon = getQueryString('coupon'); const [, setCoupon] = usePersistentBySession('coupon', []); @@ -273,7 +274,7 @@ function AuthProvider({ children, pageProps }) { if (responseData?.silent !== true && responseData?.non_field_errors?.length > 0) { for (let i = 0; i < responseData.non_field_errors?.length; i += 1) { const indexFromOne = i + 1; - toast({ + createToast({ position: 'top', status: 'error', title: responseData.non_field_errors[i], @@ -420,7 +421,7 @@ function AuthProvider({ children, pageProps }) { .then((resp) => { const data = resp?.data; if (data === undefined) { - toast({ + createToast({ position: 'top', status: 'info', title: t('signup:alert-message.email-already-sent'), @@ -428,7 +429,7 @@ function AuthProvider({ children, pageProps }) { duration: 6000, }); } else { - toast({ + createToast({ position: 'top', status: 'success', title: t('signup:alert-message.email-sent-to', { email: data?.email }), diff --git a/src/common/hooks/useCohortHandler.js b/src/common/hooks/useCohortHandler.js index b2ee9f26e..08870098b 100644 --- a/src/common/hooks/useCohortHandler.js +++ b/src/common/hooks/useCohortHandler.js @@ -1,6 +1,5 @@ /* eslint-disable camelcase */ import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import useAuth from './useAuth'; @@ -10,6 +9,7 @@ import useModuleHandler from './useModuleHandler'; import { processRelatedAssignments } from '../handlers/cohorts'; import bc from '../services/breathecode'; import { BREATHECODE_HOST, DOMAIN_NAME } from '../../utils/variables'; +import useCustomToast from './useCustomToast'; function useCohortHandler() { const router = useRouter(); @@ -23,7 +23,7 @@ function useCohortHandler() { sortedAssignments, userCapabilities, } = state; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'fetching-role-cohort-error' }); const accessToken = getStorageItem('accessToken'); const assetSlug = router?.query?.lessonSlug; const assetType = router?.query?.lesson; @@ -73,7 +73,7 @@ function useCohortHandler() { setCohortProgram(programData.data); } catch (err) { console.log(err); - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-role', { role: currentAcademy?.role }), description: err.message, @@ -136,7 +136,7 @@ function useCohortHandler() { return handleRedirectToPublicPage(); } catch (error) { handleRedirectToPublicPage(); - toast({ + createToast({ position: 'top', title: t('alert-message:invalid-cohort-slug'), status: 'error', diff --git a/src/common/hooks/useCustomToast.jsx b/src/common/hooks/useCustomToast.jsx index c973cc684..a93d70629 100644 --- a/src/common/hooks/useCustomToast.jsx +++ b/src/common/hooks/useCustomToast.jsx @@ -3,67 +3,100 @@ import { Box, Button, Flex, useToast } from '@chakra-ui/react'; import Icon from '../components/Icon'; const bgColors = { - info: 'blue.500', - warning: 'yellow.500', - error: 'red.500', - success: 'green.500', + info: { background: '#F9F9F9', color: '#3A3A3A', borderColor: '#DADADA' }, + warning: { background: '#ffefcc', color: '#975100', borderColor: '#FFB718' }, + error: { background: '#fee8e8', color: '#EB5757', borderColor: '#EB5757' }, + success: { background: '#e0ffe8', color: '#00a33d', borderColor: '#00bb2d' }, }; const useCustomToast = ({ - toastIdRef, - title = 'Already have an account?', - status = 'info', - position = 'top', - duration = 16000, - content, - isClosable = true, + toastId, }) => { const toast = useToast(); const closeToast = () => { - if (toastIdRef.current) { - toast.close(toastIdRef.current); - } + toast.close(toastId); }; - const createToast = () => { - toastIdRef.current = toast({ + const createToast = ({ + title = 'Already have an account?', + status = 'success', + position = 'top', + maxWidth = '1200px', + width = '90%', + duration = 16000, + description, + actions = null, + isClosable = true, + }) => { + const toastColors = bgColors[status]; + + toastId = toast({ position, status, render: () => ( - - - + + + {title} {isClosable && ( )} - {content} + + {description} + + {actions?.length > 0 && ( + + {actions.map((action) => ( + + ))} + + )} ), duration, diff --git a/src/common/hooks/useModuleHandler.js b/src/common/hooks/useModuleHandler.js index c09bd341b..b02b7c0af 100644 --- a/src/common/hooks/useModuleHandler.js +++ b/src/common/hooks/useModuleHandler.js @@ -1,13 +1,13 @@ -import { useToast } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import useModuleMap from '../store/actions/moduleMapAction'; import bc from '../services/breathecode'; import { reportDatalayer } from '../../utils/requests'; import { getBrowserInfo } from '../../utils'; +import useCustomToast from './useCustomToast'; function useModuleHandler() { const { t } = useTranslation('alert-message'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: ' assignment-update-task' }); const { setTaskTodo, setCohortProgram, state, setCurrentTask, setSubTasks, setNextModule, setPrevModule } = useModuleMap(); const { taskTodo } = state; @@ -32,7 +32,7 @@ function useModuleHandler() { taskToUpdate, // key item (updated) ...taskTodo.slice(keyIndex + 1), // after keyIndex (exclusive) ]); - toast({ + createToast({ position: 'top', title: t('alert-message:assignment-updated'), status: 'success', @@ -42,7 +42,7 @@ function useModuleHandler() { closeSettings(); } catch (error) { console.log(error); - toast({ + createToast({ position: 'top', title: t('alert-message:assignment-update-error'), status: 'error', @@ -94,7 +94,7 @@ function useModuleHandler() { agent: getBrowserInfo(), }, }); - toast({ + createToast({ position: 'top', title: isDelivering ? t('alert-message:delivery-success') @@ -107,7 +107,7 @@ function useModuleHandler() { } } catch (error) { console.log(error); - toast({ + createToast({ position: 'top', title: t('alert-message:delivery-error'), status: 'error', @@ -126,7 +126,7 @@ function useModuleHandler() { const response = await bc.todo({}).add(newTasks); if (response.status < 400) { - toast({ + createToast({ position: 'top', title: label ? t('alert-message:module-started', { title: label }) @@ -143,7 +143,7 @@ function useModuleHandler() { } } catch (err) { console.log('error_ADD_TASK 🔴 ', err); - toast({ + createToast({ position: 'top', title: t('alert-message:module-start-error'), status: 'error', diff --git a/src/common/hooks/useSubscribeToPlan.jsx b/src/common/hooks/useSubscribeToPlan.jsx index 4226f3ff3..0c5be1f57 100644 --- a/src/common/hooks/useSubscribeToPlan.jsx +++ b/src/common/hooks/useSubscribeToPlan.jsx @@ -1,5 +1,5 @@ import { useMemo, useState } from 'react'; -import { Box, ListItem, UnorderedList, useToast, Button, Image } from '@chakra-ui/react'; +import { Box, ListItem, UnorderedList, Button, Image } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import SimpleModal from '../components/SimpleModal'; @@ -10,6 +10,7 @@ import Heading from '../components/Heading'; import { toCapitalize, unSlugify } from '../../utils'; import Icon from '../components/Icon'; import { generatePlan } from '../handlers/subscriptions'; +import useCustomToast from './useCustomToast'; const useSubscribeToPlan = ({ enableRedirectOnCTA = false, redirectTo = '/choose-program', onClose: onExternalClose = () => {} } = {}) => { const { t } = useTranslation(['common']); @@ -18,7 +19,7 @@ const useSubscribeToPlan = ({ enableRedirectOnCTA = false, redirectTo = '/choose const [isInProcessOfSubscription, setIsInProcessOfSubscription] = useState(false); const { handleChecking, handlePayment } = useSignup({ disableRedirectAfterSuccess: true }); const { modal } = useStyle(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'handling-payment-error' }); const [isCheckingSuccess, setIsCheckingSuccess] = useState(false); const handleSubscribeToPlan = ({ slug, accessToken, onSubscribedToPlan = () => {}, disableRedirects = false }) => new Promise((resolve, reject) => { @@ -50,7 +51,7 @@ const useSubscribeToPlan = ({ enableRedirectOnCTA = false, redirectTo = '/choose .catch((error) => { reject(error); console.error('Error handling payment', error); - toast({ + createToast({ position: 'top', title: t('alert-message:payment-error'), status: 'error', diff --git a/src/common/store/actions/signupAction.js b/src/common/store/actions/signupAction.js index bf2b71442..9ff41646c 100644 --- a/src/common/store/actions/signupAction.js +++ b/src/common/store/actions/signupAction.js @@ -1,7 +1,6 @@ /* eslint-disable camelcase */ /* eslint-disable no-unsafe-optional-chaining */ import { useSelector, useDispatch } from 'react-redux'; -import { useToast } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import { @@ -18,6 +17,7 @@ import useSession from '../../hooks/useSession'; import useAuth from '../../hooks/useAuth'; import { reportDatalayer } from '../../../utils/requests'; import { generatePlan, getTranslations } from '../../handlers/subscriptions'; +import useCustomToast from '../../hooks/useCustomToast'; // eslint-disable-next-line no-unused-vars const useSignup = () => { @@ -26,7 +26,7 @@ const useSignup = () => { const state = useSelector((sl) => sl.signupReducer); const [, setSubscriptionProcess] = usePersistent('subscription-process', null); const { t } = useTranslation('signup'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'error-payment-transaction' }); const router = useRouter(); const { locale } = router; const dispatch = useDispatch(); @@ -203,7 +203,7 @@ const useSignup = () => { } } if (transactionData === undefined || transactionData.status >= 400) { - toast({ + createToast({ position: 'top', title: t('alert-message:payment-error'), status: 'error', diff --git a/src/common/store/actions/subscriptionAction.js b/src/common/store/actions/subscriptionAction.js index d56e90e9e..5d8f43ee1 100644 --- a/src/common/store/actions/subscriptionAction.js +++ b/src/common/store/actions/subscriptionAction.js @@ -1,12 +1,12 @@ import { useSelector, useDispatch } from 'react-redux'; -import { useToast } from '@chakra-ui/react'; import { CANCEL_SUBSCRIPTION, FETCH_SUBSCRIPTIONS, IS_LOADING } from '../types'; import bc from '../../services/breathecode'; import profileHandlers from '../../../js_modules/profile/Subscriptions/handlers'; +import useCustomToast from '../../hooks/useCustomToast'; const useSubscriptionsHandler = () => { const state = useSelector((st) => st.subscriptionsReducer); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'canceling-subscription-error-action' }); const dispatch = useDispatch(); const { getPlanOffer, @@ -71,7 +71,7 @@ const useSubscriptionsHandler = () => { resolve(data); }) .catch((err) => { - toast({ + createToast({ position: 'top', title: 'Error cancelling subscription', status: 'error', diff --git a/src/common/views/StudentAssignments.jsx b/src/common/views/StudentAssignments.jsx index 2b691e97e..69ccbb0fb 100644 --- a/src/common/views/StudentAssignments.jsx +++ b/src/common/views/StudentAssignments.jsx @@ -6,7 +6,6 @@ import { Box, Avatar, Flex, - useToast, } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import bc from '../services/breathecode'; @@ -18,6 +17,7 @@ import { ReviewModal, NoInfoModal, DeliverModal, DetailsModal } from '../../js_m import LoaderScreen from '../components/LoaderScreen'; import InfiniteScroll from '../components/InfiniteScroll'; import { ORIGIN_HOST } from '../../utils/variables'; +import useCustomToast from '../hooks/useCustomToast'; const StudentsRows = forwardRef(({ currentStudentList, syllabusData, selectedCohort, setCurrentTask, setDeliveryUrl }, ref) => { const { t } = useTranslation('assignments'); @@ -25,7 +25,7 @@ const StudentsRows = forwardRef(({ currentStudentList, syllabusData, selectedCoh const { query } = router; const { academy, cohortSlug } = query; const { formatTimeString } = useFormatTimeString(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'student-assignment-review-error' }); const { hexColor } = useStyle(); const getStatus = (task) => { @@ -60,7 +60,7 @@ const StudentsRows = forwardRef(({ currentStudentList, syllabusData, selectedCoh } setCurrentTask({ ...task, status, file }); } catch (e) { - toast({ + createToast({ position: 'top', title: t('alert-message:review-url-error'), status: 'error', diff --git a/src/js_modules/assignmentHandler/PopoverHandler.jsx b/src/js_modules/assignmentHandler/PopoverHandler.jsx index 39b5f2b1a..e1f11c526 100644 --- a/src/js_modules/assignmentHandler/PopoverHandler.jsx +++ b/src/js_modules/assignmentHandler/PopoverHandler.jsx @@ -1,6 +1,6 @@ /* eslint-disable react/jsx-no-useless-fragment */ import { - Box, Button, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, PopoverTrigger, useToast, + Box, Button, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, PopoverTrigger, } from '@chakra-ui/react'; import { useState } from 'react'; import PropTypes from 'prop-types'; @@ -13,6 +13,7 @@ import Text from '../../common/components/Text'; import Link from '../../common/components/NextChakraLink'; import useStyle from '../../common/hooks/useStyle'; import useCohortHandler from '../../common/hooks/useCohortHandler'; +import useCustomToast from '../../common/hooks/useCustomToast'; function PopoverHandler({ task, githubUrl, haveGithubDomain }) { const [settingsOpen, setSettingsOpen] = useState(false); @@ -23,7 +24,7 @@ function PopoverHandler({ task, githubUrl, haveGithubDomain }) { const [fileData, setFileData] = useState([]); const { t } = useTranslation('assignments'); const { backgroundColor, hexColor } = useStyle(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'current-task-no-files-error' }); const isUrl = assetData?.delivery_formats.includes('url'); const noDeliveryFormat = assetData?.delivery_formats.includes('no_delivery'); @@ -45,7 +46,7 @@ function PopoverHandler({ task, githubUrl, haveGithubDomain }) { setFileData(respData); setSettingsOpen(true); } else { - toast({ + createToast({ position: 'top', title: t('alert-message:current-task-no-files'), status: 'error', diff --git a/src/js_modules/assignmentHandler/index.jsx b/src/js_modules/assignmentHandler/index.jsx index 5884d42a3..c2aa47722 100644 --- a/src/js_modules/assignmentHandler/index.jsx +++ b/src/js_modules/assignmentHandler/index.jsx @@ -1,6 +1,6 @@ /* eslint-disable react/no-unstable-nested-components */ import { - Box, Button, Link, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useToast, useColorModeValue, useDisclosure, + Box, Button, Link, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useColorModeValue, useDisclosure, } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; @@ -17,6 +17,7 @@ import useStyle from '../../common/hooks/useStyle'; import { ORIGIN_HOST } from '../../utils/variables'; import ReviewModalComponent from '../../common/components/ReviewModal'; import UndoApprovalModal from '../../common/components/UndoApprovalModal'; +import useCustomToast from '../../common/hooks/useCustomToast'; export function DetailsModal({ currentTask, projectLink, updpateAssignment, isOpen, onClose, readOnly, @@ -148,7 +149,7 @@ function DeliverHandler({ const { isOpen, onOpen, onClose } = useDisclosure(); const [isLoading, setIsLoading] = useState(false); const [deliveryUrl, setDeliveryUrl] = useState(''); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'index-review-error' }); const [copied, setCopied] = useState(false); const router = useRouter(); const { academy } = router.query; @@ -179,7 +180,7 @@ function DeliverHandler({ }) .catch((e) => { console.log(e); - toast({ + createToast({ position: 'top', title: t('alert-message:review-url-error'), status: 'error', @@ -208,7 +209,7 @@ function DeliverHandler({ export function NoInfoModal({ isOpen, onClose, selectedCohort }) { const { t } = useTranslation('assignments'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'success-msg-error' }); const [isSyncOpen, setIsSyncOpen] = useState(false); const { hexColor } = useStyle(); const borderColor2 = useColorModeValue('gray.250', 'gray.500'); @@ -220,7 +221,7 @@ export function NoInfoModal({ isOpen, onClose, selectedCohort }) { const { message } = resp.data; - toast({ + createToast({ position: 'top', title: 'Success', description: message, @@ -229,7 +230,7 @@ export function NoInfoModal({ isOpen, onClose, selectedCohort }) { }); } catch (e) { console.log(e); - toast({ + createToast({ position: 'top', title: t('error-msg'), status: 'error', diff --git a/src/js_modules/checkout/ChooseDate.jsx b/src/js_modules/checkout/ChooseDate.jsx index cf29ac477..b74a1be80 100644 --- a/src/js_modules/checkout/ChooseDate.jsx +++ b/src/js_modules/checkout/ChooseDate.jsx @@ -1,5 +1,5 @@ /* eslint-disable no-unsafe-optional-chaining */ -import { Box, Button, Flex, useToast } from '@chakra-ui/react'; +import { Box, Button, Flex } from '@chakra-ui/react'; import { es } from 'date-fns/locale'; import { format } from 'date-fns'; import PropTypes from 'prop-types'; @@ -9,11 +9,12 @@ import useTranslation from 'next-translate/useTranslation'; import Text from '../../common/components/Text'; import useSignup from '../../common/store/actions/signupAction'; import bc from '../../common/services/breathecode'; +import useCustomToast from '../../common/hooks/useCustomToast'; function ChooseDate({ cohort, ...rest }) { const [isLoading, setIsLoading] = useState(false); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'no-plan-configuration-info' }); const { handleChecking, nextStep, setCohortPlans } = useSignup(); const { t } = useTranslation('signup'); @@ -77,7 +78,7 @@ function ChooseDate({ cohort, ...rest }) { }).getCohortPlans() .then(({ data }) => { if (data.length === 0) { - toast({ + createToast({ position: 'top', title: t('alert-message:no-plan-configuration'), status: 'info', diff --git a/src/js_modules/checkout/ChooseYourClass.jsx b/src/js_modules/checkout/ChooseYourClass.jsx index 63d87fe5d..c14ce568d 100644 --- a/src/js_modules/checkout/ChooseYourClass.jsx +++ b/src/js_modules/checkout/ChooseYourClass.jsx @@ -1,5 +1,5 @@ import { - Box, Button, Input, useToast, + Box, Button, Input, } from '@chakra-ui/react'; import PropTypes from 'prop-types'; import useTranslation from 'next-translate/useTranslation'; @@ -14,6 +14,7 @@ import ChooseDate from './ChooseDate'; import useStyle from '../../common/hooks/useStyle'; import { reportDatalayer } from '../../utils/requests'; import { CardSkeleton } from '../../common/components/Skeleton'; +import useCustomToast from '../../common/hooks/useCustomToast'; function LoaderContent({ cohortIsLoading }) { const { t } = useTranslation('signup'); @@ -29,7 +30,7 @@ function LoaderContent({ cohortIsLoading }) { cardHeight="120px" /> ) : ( - + ); } @@ -42,7 +43,7 @@ function ChooseYourClass({ const [isLoading, setIsLoading] = useState(false); const [coords, setCoords] = useState(null); const [addressValue, setAddressValue] = useState(''); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'cohort-google-maps-class' }); const autoCompleteRef = useRef(); const inputRef = useRef(); const buttonRef = useRef(); @@ -96,7 +97,7 @@ function ChooseYourClass({ setAvailableDates(filteredCohorts); }) .catch((error) => { - toast({ + createToast({ position: 'top', title: t('alert-message:something-went-wrong-fetching-cohorts'), description: error.message, @@ -136,7 +137,7 @@ function ChooseYourClass({ }); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:google-maps-no-coincidences'), status: 'warning', diff --git a/src/js_modules/checkout/PaymentInfo.jsx b/src/js_modules/checkout/PaymentInfo.jsx index 9604a8e72..064fef4de 100644 --- a/src/js_modules/checkout/PaymentInfo.jsx +++ b/src/js_modules/checkout/PaymentInfo.jsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import useTranslation from 'next-translate/useTranslation'; import { - Box, Button, Flex, useToast, + Box, Button, Flex, } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import Heading from '../../common/components/Heading'; @@ -25,6 +25,7 @@ import Text from '../../common/components/Text'; import AcordionList from '../../common/components/AcordionList'; import LoaderScreen from '../../common/components/LoaderScreen'; import NextChakraLink from '../../common/components/NextChakraLink'; +import useCustomToast from '../../common/hooks/useCustomToast'; function PaymentInfo() { const { t, lang } = useTranslation('signup'); @@ -51,7 +52,7 @@ function PaymentInfo() { const [readyToRefetch, setReadyToRefetch] = useState(false); const [cohortFound, setCohortFound] = useState(undefined); const [timeElapsed, setTimeElapsed] = useState(0); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'payment-info-data-detail' }); const redirect = getStorageItem('redirect'); const redirectedFrom = getStorageItem('redirected-from'); const router = useRouter(); @@ -160,7 +161,7 @@ function PaymentInfo() { .then(async (resp) => { const dataRequested = await resp.json(); if (resp.status >= 400) { - toast({ + createToast({ position: 'top', title: dataRequested?.detail, status: 'info', diff --git a/src/js_modules/checkout/Summary.jsx b/src/js_modules/checkout/Summary.jsx index 9087048fd..f7a6e75f7 100644 --- a/src/js_modules/checkout/Summary.jsx +++ b/src/js_modules/checkout/Summary.jsx @@ -1,6 +1,6 @@ /* eslint-disable camelcase */ /* eslint-disable no-restricted-globals */ -import { Box, Button, Flex, useColorModeValue, useToast } from '@chakra-ui/react'; +import { Box, Button, Flex, useColorModeValue } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { Fragment, useState, useEffect } from 'react'; import { useRouter } from 'next/router'; @@ -18,6 +18,7 @@ import axiosInstance from '../../axios'; import useCohortHandler from '../../common/hooks/useCohortHandler'; import useModuleHandler from '../../common/hooks/useModuleHandler'; import { getCohort } from '../../common/handlers/cohorts'; +import useCustomToast from '../../common/hooks/useCustomToast'; function Summary() { const { t, lang } = useTranslation('signup'); @@ -36,7 +37,7 @@ function Summary() { } = useSignup(); const [hasMounted, setHasMounted] = useState(false); const { dateProps, checkoutData, selectedPlanCheckoutData, planProps } = state; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'payment-request-data-detail-error' }); const [isSubmitting, setIsSubmitting] = useState(false); const [readyToRefetch, setReadyToRefetch] = useState(false); const [declinedPaymentProps, setDeclinedPaymentProps] = useState({ @@ -190,7 +191,7 @@ function Summary() { .then(async (resp) => { const dataRequested = await resp.json(); if (resp.status >= 400) { - toast({ + createToast({ position: 'top', title: dataRequested?.detail, status: 'error', @@ -334,7 +335,7 @@ function Summary() { }) .catch(() => { setLoader('plan', false); - toast({ + createToast({ position: 'top', title: t('alert-message:payment-error'), status: 'error', diff --git a/src/js_modules/moduleMap/module.jsx b/src/js_modules/moduleMap/module.jsx index c5e5639f8..e8a7c7f02 100644 --- a/src/js_modules/moduleMap/module.jsx +++ b/src/js_modules/moduleMap/module.jsx @@ -1,7 +1,6 @@ import { Box, Button, - useToast, Link, } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; @@ -18,6 +17,7 @@ import Icon from '../../common/components/Icon'; import { reportDatalayer } from '../../utils/requests'; import { getBrowserInfo } from '../../utils'; // import { usePersistent } from '../../common/hooks/usePersistent'; +import useCustomToast from '../../common/hooks/useCustomToast'; function Module({ data, currIndex, isDisabled, onDisabledClick, variant, @@ -32,7 +32,7 @@ function Module({ const [, setUpdatedTask] = useState(null); const [showModal, setShowModal] = useState(false); const { hexColor } = useStyle(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'something-wrong-module' }); const currentSlug = data.slug ? data.slug : ''; const currentTask = taskTodo?.length > 0 ? taskTodo.find((el) => el?.task_type === data?.task_type @@ -101,7 +101,7 @@ function Module({ } setSettingsOpen(!settingsOpen); } else { - toast({ + createToast({ position: 'top', title: t('alert-message:something-went-wrong'), status: 'error', diff --git a/src/js_modules/profile/Information.jsx b/src/js_modules/profile/Information.jsx index 53a90f21a..845b3ad67 100644 --- a/src/js_modules/profile/Information.jsx +++ b/src/js_modules/profile/Information.jsx @@ -1,4 +1,4 @@ -import { Avatar, Box, Button, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Popover, PopoverArrow, PopoverBody, PopoverContent, PopoverTrigger, Slider, SliderFilledTrack, SliderThumb, SliderTrack, useMediaQuery, useToast } from '@chakra-ui/react'; +import { Avatar, Box, Button, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Popover, PopoverArrow, PopoverBody, PopoverContent, PopoverTrigger, Slider, SliderFilledTrack, SliderThumb, SliderTrack, useMediaQuery } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import Head from 'next/head'; import { useCallback, useEffect, useState } from 'react'; @@ -12,11 +12,12 @@ import { location } from '../../utils'; import getCroppedImg from '../../utils/cropImage'; import Icon from '../../common/components/Icon'; import useUploadFileInChunks from '../../common/hooks/useUploadFileInChunks'; +import useCustomToast from '../../common/hooks/useCustomToast'; function Information() { const { t } = useTranslation('profile'); const { user, updateProfile } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'information-picture-submitting' }); const [showModal, setShowModal] = useState(false); const [isLoading, setIsLoading] = useState(false); const [crop, setCrop] = useState({ x: 0, y: 0 }); @@ -37,7 +38,7 @@ function Information() { // Validar que el archivo sea de tipo imagen if (file && !fileTypes.includes(file.type)) { - toast({ + createToast({ position: 'top', title: t('alert-message:file-type-error', { type: file.type.split('/')[1] }), status: 'warning', @@ -103,7 +104,7 @@ function Information() { } else { throw new Error('Error uploading profile picture'); } - toast({ + createToast({ position: 'top', title: t('alert-message:submitting-picture-success'), status: 'success', @@ -112,7 +113,7 @@ function Information() { } catch (e) { console.error(e); setIsLoading(false); - toast({ + createToast({ position: 'top', title: t('alert-message:error-submitting-picture'), status: 'error', diff --git a/src/js_modules/profile/Subscriptions/handlers.jsx b/src/js_modules/profile/Subscriptions/handlers.jsx index 3aadf4581..b9fad0d9f 100644 --- a/src/js_modules/profile/Subscriptions/handlers.jsx +++ b/src/js_modules/profile/Subscriptions/handlers.jsx @@ -1,5 +1,4 @@ /* eslint-disable no-unsafe-optional-chaining */ -import { useToast } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import { useRouter } from 'next/router'; import PropTypes from 'prop-types'; @@ -7,11 +6,12 @@ import useStyle from '../../../common/hooks/useStyle'; import bc from '../../../common/services/breathecode'; import useSignup from '../../../common/store/actions/signupAction'; import { toCapitalize, unSlugify } from '../../../utils'; +import useCustomToast from '../../../common/hooks/useCustomToast'; function profileHandlers() { const { t } = useTranslation('profile'); const { reverseFontColor, fontColor, lightColor } = useStyle(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'getting-plan-offer-error' }); const router = useRouter(); const { setPaymentStatus } = useSignup(); @@ -261,7 +261,7 @@ function profileHandlers() { router.push(`/checkout?plan=${planData?.slug}`); } } else { - toast({ + createToast({ position: 'top', title: t('alert-message:error-getting-plan'), status: 'error', @@ -273,7 +273,7 @@ function profileHandlers() { }) .catch(() => { reject(); - toast({ + createToast({ position: 'top', title: t('alert-message:error-getting-plan'), status: 'error', @@ -463,7 +463,7 @@ function profileHandlers() { }) .catch(() => { reject(); - toast({ + createToast({ position: 'top', title: t('alert-message:error-getting-offer'), status: 'error', diff --git a/src/js_modules/syllabus/TaskCodeRevisions.jsx b/src/js_modules/syllabus/TaskCodeRevisions.jsx index 052e9ada3..068bd4de4 100644 --- a/src/js_modules/syllabus/TaskCodeRevisions.jsx +++ b/src/js_modules/syllabus/TaskCodeRevisions.jsx @@ -1,4 +1,4 @@ -import { Box, Button, Divider, Flex, Textarea, useToast } from '@chakra-ui/react'; +import { Box, Button, Divider, Flex, Textarea } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import useTranslation from 'next-translate/useTranslation'; import useAuth from '../../common/hooks/useAuth'; @@ -11,6 +11,7 @@ import Heading from '../../common/components/Heading'; import Text from '../../common/components/Text'; import MarkDownParser from '../../common/components/MarkDownParser'; import { error } from '../../utils/logging'; +import useCustomToast from '../../common/hooks/useCustomToast'; const inputReviewRateCommentLimit = 100; const defaultReviewRateData = { @@ -24,7 +25,7 @@ function TaskCodeRevisions() { const { currentTask } = useModuleHandler(); const { featuredLight, hexColor, backgroundColor, backgroundColor4 } = useStyle(); const { isAuthenticatedWithRigobot } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'something-went-wrong-error-task' }); const [contextData, setContextData] = useState({ code_revisions: [], revision_content: {}, @@ -80,7 +81,7 @@ function TaskCodeRevisions() { code_revisions: codeRevisionsSortedByDate, })); } else { - toast({ + createToast({ title: t('alert-message:something-went-wrong'), description: `Cannot get code revisions: ${data?.detail}`, status: 'error', diff --git a/src/pages/accept-invite.jsx b/src/pages/accept-invite.jsx index d41899ef0..374ec3e81 100644 --- a/src/pages/accept-invite.jsx +++ b/src/pages/accept-invite.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Box, Image, Flex, Button, FormControl, FormLabel, Input, Checkbox, useToast, FormErrorMessage } from '@chakra-ui/react'; +import { Box, Image, Flex, Button, FormControl, FormLabel, Input, Checkbox, FormErrorMessage } from '@chakra-ui/react'; import { Form, Formik, Field } from 'formik'; import { useRouter } from 'next/router'; import PropTypes from 'prop-types'; @@ -12,6 +12,7 @@ import validationSchema from '../common/components/Forms/validationSchemas'; import NextChakraLink from '../common/components/NextChakraLink'; import Text from '../common/components/Text'; import Heading from '../common/components/Heading'; +import useCustomToast from '../common/hooks/useCustomToast'; function FormField({ name, label, type = 'text', isReadOnly = false, placeholder }) { return ( @@ -36,7 +37,7 @@ function FormField({ name, label, type = 'text', isReadOnly = false, placeholder } function AcceptInvite() { - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'accept-invitation-successfull-error' }); const router = useRouter(); const { t, lang } = useTranslation('accept-invite'); const { isAuthenticated, user, isLoading, login } = useAuth(); @@ -85,7 +86,7 @@ function AcceptInvite() { const res = await bc.auth().invites().accept(id); const { status } = res; if (status >= 200 && status < 400) { - toast({ + createToast({ title: t('alert-message:invitation-accepted-cohort', { cohortName: cohort.name }), position: 'top', status: 'success', @@ -99,7 +100,7 @@ function AcceptInvite() { } } catch (e) { console.log(e); - toast({ + createToast({ title: t('alert-message:invitation-error'), position: 'top', status: 'error', @@ -115,7 +116,7 @@ function AcceptInvite() { .then((data) => { actions.setSubmitting(false); if (data.status === 200) { - toast({ + createToast({ position: 'top', title: t('alert-message:welcome'), status: 'success', @@ -128,7 +129,7 @@ function AcceptInvite() { }) .catch(() => { actions.setSubmitting(false); - toast({ + createToast({ position: 'top', title: t('alert-message:account-not-found'), status: 'error', @@ -155,14 +156,14 @@ function AcceptInvite() { const result = await resp.json(); if (resp.status >= 400) { - toast({ + createToast({ title: result.detail, status: 'error', duration: 9000, isClosable: true, }); } else if (resp.status >= 200 && resp.status <= 299) { - toast({ + createToast({ title: 'Successfully accepted!', status: 'success', duration: 9000, @@ -174,7 +175,7 @@ function AcceptInvite() { actions.setSubmitting(false); } catch (e) { console.log(e); - toast({ + createToast({ title: e?.message || t('error'), status: 'error', duration: 9000, diff --git a/src/pages/bootcamp/[course_slug].jsx b/src/pages/bootcamp/[course_slug].jsx index d4e566186..adff284ee 100644 --- a/src/pages/bootcamp/[course_slug].jsx +++ b/src/pages/bootcamp/[course_slug].jsx @@ -40,6 +40,7 @@ import MktTwoColumnSideImage from '../../common/components/MktTwoColumnSideImage import { AvatarSkeletonWrapped } from '../../common/components/Skeleton'; import CouponTopBar from '../../common/components/CouponTopBar'; import completions from './completion-jobs.json'; +import useCustomToast from '../../common/hooks/useCustomToast'; export async function getStaticPaths({ locales }) { const mktQueryString = parseQuerys({ @@ -116,7 +117,8 @@ function CoursePage({ data, syllabus }) { const { hexColor, backgroundColor, fontColor, borderColor, complementaryBlue, featuredColor } = useStyle(); const { isRigoInitialized, rigo } = useRigo(); const { setCohortSession } = useCohortHandler(); - const toast = useToast(); + // const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'choose-program-pricing-detail' }); const [isFetching, setIsFetching] = useState(false); const [readyToRefetch, setReadyToRefetch] = useState(false); const [timeElapsed, setTimeElapsed] = useState(0); @@ -298,7 +300,7 @@ function CoursePage({ data, syllabus }) { setReadyToRefetch(true); } if (dataRequested?.status_code === 400) { - toast({ + createToast({ position: 'top', title: dataRequested?.detail, status: 'info', @@ -310,7 +312,7 @@ function CoursePage({ data, syllabus }) { }, 600); } if (dataRequested?.status_code > 400) { - toast({ + createToast({ position: 'top', title: dataRequested?.detail, status: 'error', @@ -353,7 +355,7 @@ function CoursePage({ data, syllabus }) { setIsFetching(false); if (withAlert) { - toast({ + createToast({ position: 'top', title: t('dashboard:already-have-this-cohort'), status: 'info', diff --git a/src/pages/checkout/event/[event_service_slug].jsx b/src/pages/checkout/event/[event_service_slug].jsx index 80c5102ab..29474f583 100644 --- a/src/pages/checkout/event/[event_service_slug].jsx +++ b/src/pages/checkout/event/[event_service_slug].jsx @@ -2,7 +2,6 @@ import { Box, Flex, - useToast, } from '@chakra-ui/react'; import { useState, useEffect } from 'react'; import getT from 'next-translate/getT'; @@ -21,6 +20,7 @@ import ServiceSummary from '../../../js_modules/checkout/ServiceSummary'; import SelectServicePlan from '../../../js_modules/checkout/SelectServicePlan'; import { ORIGIN_HOST } from '../../../utils/variables'; import { usePersistentBySession } from '../../../common/hooks/usePersistent'; +import useCustomToast from '../../../common/hooks/useCustomToast'; export const getStaticPaths = async ({ locales }) => { const res = await bc.payment().getAllEventTypeSets(); @@ -87,7 +87,7 @@ function ServiceSlug() { axiosInstance.defaults.headers.common['Accept-Language'] = router.locale; const { user, isAuthenticated, isLoading } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'event-service-error' }); const eventTypeSetSlug = event_service_slug; const accessToken = getStorageItem('accessToken'); @@ -208,7 +208,7 @@ function ServiceSlug() { .then(async (resp) => { const respData = await resp.json(); if (resp.status > 400) { - toast({ + createToast({ title: respData.detail, status: 'error', duration: 6000, diff --git a/src/pages/checkout/index.jsx b/src/pages/checkout/index.jsx index c8df07d62..599f23c55 100644 --- a/src/pages/checkout/index.jsx +++ b/src/pages/checkout/index.jsx @@ -10,7 +10,6 @@ import { InputGroup, InputRightElement, Skeleton, - useToast, Accordion, AccordionButton, AccordionIcon, @@ -50,6 +49,7 @@ import { reportDatalayer } from '../../utils/requests'; import { getTranslations, processPlans } from '../../common/handlers/subscriptions'; import Icon from '../../common/components/Icon'; import { usePersistentBySession } from '../../common/hooks/usePersistent'; +import useCustomToast from '../../common/hooks/useCustomToast'; export const getStaticProps = async ({ locale, locales }) => { const t = await getT(locale, 'signup'); @@ -114,7 +114,7 @@ function Checkout() { axiosInstance.defaults.headers.common['Accept-Language'] = router.locale; const { user, isAuthenticated, isLoading } = useAuth(); const { userSession } = useSession(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'coupon-plan-email-detail' }); const plan = getQueryString('plan'); const queryPlans = getQueryString('plans'); const queryPlanId = getQueryString('plan_id'); @@ -193,7 +193,7 @@ function Checkout() { const alreadyAppliedCoupon = (selfAppliedCoupon?.slug && selfAppliedCoupon?.slug === discountCode) || (selfAppliedCoupon?.slug && selfAppliedCoupon?.slug === couponValue); if (alreadyAppliedCoupon) { - toast({ + createToast({ position: 'top', title: t('signup:alert-message.coupon-already-applied'), status: 'info', @@ -272,7 +272,7 @@ function Checkout() { }) .catch((err) => { if (err) { - toast({ + createToast({ position: 'top', title: t('alert-message:no-plan-configuration'), status: 'info', @@ -374,7 +374,7 @@ function Checkout() { const respData = await resp.json(); if (resp.status > 400) { setShowChooseClass(true); - toast({ + createToast({ title: respData.detail, status: 'error', duration: 6000, @@ -410,7 +410,7 @@ function Checkout() { if (!resp) { setLoader('plan', false); router.push('/pricing'); - toast({ + createToast({ position: 'top', title: t('alert-message:no-plan-configuration'), status: 'error', @@ -427,7 +427,7 @@ function Checkout() { if ((resp && resp?.status >= 400) || resp?.data.length === 0) { setShowChooseClass(true); - toast({ + createToast({ position: 'top', title: t('alert-message:no-plan-configuration'), status: 'info', @@ -503,7 +503,7 @@ function Checkout() { }) .catch(() => { setLoader('plan', false); - toast({ + createToast({ position: 'top', title: t('alert-message:no-plan-configuration'), status: 'info', @@ -645,7 +645,7 @@ function Checkout() { .then((resp) => { const data = resp?.data; if (data === undefined) { - toast({ + createToast({ position: 'top', status: 'info', title: t('signup:alert-message.email-already-sent'), @@ -653,7 +653,7 @@ function Checkout() { duration: 6000, }); } else { - toast({ + createToast({ position: 'top', status: 'success', title: t('signup:alert-message.email-sent-to', { email: data?.email }), diff --git a/src/pages/checkout/mentorship/[mentorship_service_slug].jsx b/src/pages/checkout/mentorship/[mentorship_service_slug].jsx index 393d0cbef..3786c798d 100644 --- a/src/pages/checkout/mentorship/[mentorship_service_slug].jsx +++ b/src/pages/checkout/mentorship/[mentorship_service_slug].jsx @@ -2,7 +2,6 @@ import { Box, Flex, - useToast, } from '@chakra-ui/react'; import { useState, useEffect } from 'react'; import getT from 'next-translate/getT'; @@ -21,6 +20,7 @@ import ServiceSummary from '../../../js_modules/checkout/ServiceSummary'; import SelectServicePlan from '../../../js_modules/checkout/SelectServicePlan'; import { ORIGIN_HOST } from '../../../utils/variables'; import { usePersistentBySession } from '../../../common/hooks/usePersistent'; +import useCustomToast from '../../../common/hooks/useCustomToast'; export const getStaticPaths = async ({ locales }) => { const res = await bc.mentorship().getMentorshipServiceSets(); @@ -87,7 +87,7 @@ function ServiceSlug() { axiosInstance.defaults.headers.common['Accept-Language'] = router.locale; const { user, isAuthenticated, isLoading } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'mentorship-error' }); const mentorshipServiceSetSlug = mentorship_service_slug; const accessToken = getStorageItem('accessToken'); @@ -208,7 +208,7 @@ function ServiceSlug() { .then(async (resp) => { const respData = await resp.json(); if (resp.status > 400) { - toast({ + createToast({ title: respData.detail, status: 'error', duration: 6000, diff --git a/src/pages/choose-program/index.jsx b/src/pages/choose-program/index.jsx index 4e7df5e7f..da6632d54 100644 --- a/src/pages/choose-program/index.jsx +++ b/src/pages/choose-program/index.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useMemo } from 'react'; import { - Flex, Box, Button, useToast, Skeleton, useColorModeValue, + Flex, Box, Button, Skeleton, useColorModeValue, } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; import getT from 'next-translate/getT'; @@ -30,6 +30,7 @@ import SupportSidebar from '../../common/components/SupportSidebar'; import Feedback from '../../common/components/Feedback'; import axios from '../../axios'; import LanguageSelector from '../../common/components/LanguageSelector'; +import useCustomToast from '../../common/hooks/useCustomToast'; export const getStaticProps = async ({ locale, locales }) => { const t = await getT(locale, 'choose-program'); @@ -73,7 +74,7 @@ function chooseProgram() { data: [], }); const { isAuthenticated, user, updateProfile } = useAuth(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'invitation-error-accepted' }); const commonStartColor = useColorModeValue('gray.300', 'gray.light'); const commonEndColor = useColorModeValue('gray.400', 'gray.400'); const { hexColor } = useStyle(); @@ -347,7 +348,7 @@ function chooseProgram() { ...pendingProfileAcademies, ]); } catch (e) { - toast({ + createToast({ title: t('alert-message:something-went-wrong-with', { property: 'Admissions' }), status: 'error', duration: 5000, @@ -378,14 +379,14 @@ function chooseProgram() { invList.splice(invitationIndex, 1); setInvites(invList); - toast({ + createToast({ title: t('alert-message:invitation-accepted-cohort', { cohortName }), status: 'success', duration: 9000, isClosable: true, }); } else { - toast({ + createToast({ title: t('alert-message:invitation-error'), status: 'error', duration: 5000, @@ -394,7 +395,7 @@ function chooseProgram() { } } catch (e) { console.log(e); - toast({ + createToast({ title: t('alert-message:invitation-error'), status: 'error', duration: 5000, @@ -428,14 +429,14 @@ function chooseProgram() { invList.splice(invitationIndex, 1); setInvites(invList); - toast({ + createToast({ title: t('alert-message:invitation-accepted'), status: 'success', duration: 9000, isClosable: true, }); } else { - toast({ + createToast({ title: t('alert-message:invitation-error'), status: 'error', duration: 5000, @@ -444,7 +445,7 @@ function chooseProgram() { } } catch (e) { console.log(e); - toast({ + createToast({ title: t('alert-message:invitation-error'), status: 'error', duration: 5000, diff --git a/src/pages/cohort/[cohortSlug]/[slug]/[version]/index.jsx b/src/pages/cohort/[cohortSlug]/[slug]/[version]/index.jsx index 450ea0e9f..656a97e26 100644 --- a/src/pages/cohort/[cohortSlug]/[slug]/[version]/index.jsx +++ b/src/pages/cohort/[cohortSlug]/[slug]/[version]/index.jsx @@ -2,7 +2,7 @@ import { useEffect, useState, } from 'react'; import { - Box, Flex, Container, useColorModeValue, Skeleton, useToast, + Box, Flex, Container, useColorModeValue, Skeleton, Checkbox, Input, InputGroup, InputRightElement, IconButton, keyframes, usePrefersReducedMotion, Avatar, useColorMode, Modal, ModalBody, ModalCloseButton, ModalContent, @@ -54,10 +54,11 @@ import LiveEvent from '../../../../../common/components/LiveEvent'; import FinalProject from '../../../../../common/components/FinalProject'; import useStyle from '../../../../../common/hooks/useStyle'; import Feedback from '../../../../../common/components/Feedback'; +import useCustomToast from '../../../../../common/hooks/useCustomToast'; function Dashboard() { const { t, lang } = useTranslation('dashboard'); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'fetching-teachers-students-nsync-cohort' }); const router = useRouter(); const { colorMode } = useColorMode(); const [showWarningModal, setShowWarningModal] = useState(false); @@ -91,6 +92,8 @@ function Dashboard() { ? cohortProgram?.main_technologies.split(',').map((el) => el.trim()) : []; + const isSubscriptionFreeTrial = subscriptionData?.id && subscriptionData?.status === 'FREE_TRIAL' && subscriptionData?.planOfferExists; + const academyOwner = cohortProgram?.academy_owner; const { cohortSlug, slug } = router.query; @@ -147,7 +150,7 @@ function Dashboard() { }) .catch(() => { setModalIsOpen(false); - toast({ + createToast({ position: 'top', title: t('alert-message:task-cant-sync-with-cohort'), // title: 'Some Tasks cannot synced with current cohort', @@ -164,7 +167,7 @@ function Dashboard() { id: idsParsed, }).deleteBulk() .then(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:unsynced-tasks-removed'), status: 'success', @@ -174,7 +177,7 @@ function Dashboard() { setModalIsOpen(false); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:unsynced-tasks-cant-be-removed'), status: 'error', @@ -190,7 +193,7 @@ function Dashboard() { plan: programSlug, }); router.push(`/${lang}/checkout${querys}`); - toast({ + createToast({ position: 'top', title: t('alert-message:access-denied'), status: 'error', @@ -372,7 +375,7 @@ function Dashboard() { } }).catch((err) => { console.log(err); - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-students-and-teachers'), status: 'error', @@ -390,6 +393,10 @@ function Dashboard() { // Sort all data fetched in order of taskTodo useEffect(() => { prepareTasks(); + + return () => { + setSortedAssignments([]); + }; }, [cohortProgram, taskTodo, router]); const dailyModuleData = getDailyModuleData() || ''; @@ -420,11 +427,12 @@ function Dashboard() { return ( <> - {getMandatoryProjects() && getMandatoryProjects().length > 0 && ( + {getMandatoryProjects() && getMandatoryProjects().length > 0 && !isSubscriptionFreeTrial && ( console.log('Alerta de proyectos obligatorios cerrada')} > )} - {subscriptionData?.id && subscriptionData?.status === 'FREE_TRIAL' && subscriptionData?.planOfferExists && ( + {isSubscriptionFreeTrial && ( console.log('Alerta de prueba gratuita cerrada free trial')} > { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-tasks'), status: 'error', @@ -231,7 +231,7 @@ function Assignments() { }) .catch((err) => { console.log(err); - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-personal-cohorts'), status: 'error', @@ -262,7 +262,7 @@ function Assignments() { }) .catch((err) => { console.log(err); - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-cohorts'), status: 'error', @@ -291,7 +291,7 @@ function Assignments() { setCurrentStudentCount(res?.data?.count); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-students'), status: 'error', @@ -308,7 +308,7 @@ function Assignments() { const resp = await bc.assignments().getFinalProjects(selectedCohort?.id); setFinalProjects(resp.data); } catch (e) { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-final-projects'), status: 'error', @@ -331,7 +331,7 @@ function Assignments() { const resp = await bc.assignments().putFinalProject(selectedCohort?.id, id, payload); const data = await resp.json(); if (resp.status >= 400) { - toast({ + createToast({ position: 'top', title: data.detail, status: 'error', @@ -343,7 +343,7 @@ function Assignments() { const updatedIndex = copyFinalProjects.findIndex((elem) => elem.id === id); copyFinalProjects[updatedIndex].revision_status = revisionStatus; setFinalProjects(copyFinalProjects); - toast({ + createToast({ position: 'top', title: t('alert-message:success-updating-final-projects'), status: 'success', @@ -352,7 +352,7 @@ function Assignments() { }); } } catch (e) { - toast({ + createToast({ position: 'top', title: t('alert-message:error-updating-final-project'), status: 'error', diff --git a/src/pages/cohort/[cohortSlug]/attendance.jsx b/src/pages/cohort/[cohortSlug]/attendance.jsx index f0226fbf0..cee057d7e 100644 --- a/src/pages/cohort/[cohortSlug]/attendance.jsx +++ b/src/pages/cohort/[cohortSlug]/attendance.jsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import useTranslation from 'next-translate/useTranslation'; import { format } from 'date-fns'; import { - Avatar, Box, Flex, IconButton, Input, InputGroup, InputRightElement, usePrefersReducedMotion, useToast, + Avatar, Box, Flex, IconButton, Input, InputGroup, InputRightElement, usePrefersReducedMotion, keyframes, Popover, PopoverTrigger, @@ -29,11 +29,12 @@ import handlers from '../../../common/handlers'; import { DottedTimelineSkeleton, SimpleSkeleton } from '../../../common/components/Skeleton'; import Sparkline from '../../../common/components/Sparkline'; import KPI from '../../../common/components/KPI'; +import useCustomToast from '../../../common/hooks/useCustomToast'; function Attendance() { const { t } = useTranslation('attendance'); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: ' attendance-list-found-activities' }); const [allCohorts, setAllCohorts] = useState([]); const [selectedCohort, setSelectedCohort] = useState({}); const [showSearch, setShowSearch] = useState(false); @@ -121,7 +122,7 @@ function Attendance() { setSelectedCohort(dataStruct.find((c) => c.slug === cohortSlug)); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-cohorts'), status: 'error', @@ -144,7 +145,7 @@ function Attendance() { .then((daysLog) => { if (Object.keys(daysLog).length <= 0) { setCurrentDaysLog({}); - toast({ + createToast({ position: 'top', title: t('alert-message:no-attendance-list-found'), status: 'warning', @@ -156,7 +157,7 @@ function Attendance() { } }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-activities'), status: 'error', @@ -169,7 +170,7 @@ function Attendance() { setCurrentStudentList(students); }) .catch(() => { - toast({ + createToast({ position: 'top', title: t('alert-message:error-fetching-students'), status: 'error', diff --git a/src/pages/cohort/[cohortSlug]/student/[studentId]/index.jsx b/src/pages/cohort/[cohortSlug]/student/[studentId]/index.jsx index cf1235b80..e3fc9b2d1 100644 --- a/src/pages/cohort/[cohortSlug]/student/[studentId]/index.jsx +++ b/src/pages/cohort/[cohortSlug]/student/[studentId]/index.jsx @@ -6,7 +6,6 @@ import { Divider, useColorModeValue, Flex, - useToast, Modal, ModalOverlay, ModalContent, @@ -35,6 +34,7 @@ import KPI from '../../../../../common/components/KPI'; import Link from '../../../../../common/components/NextChakraLink'; import { isWindow } from '../../../../../utils'; import axiosInstance from '../../../../../axios'; +import useCustomToast from '../../../../../common/hooks/useCustomToast'; const activitiesTemplate = { invite_created: { @@ -108,7 +108,7 @@ const assetsDictionary = { function StudentReport() { const { t } = useTranslation('student'); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'no-task-url-error' }); const { query } = router; const { cohortSlug, studentId, academy } = query; const [selectedCohortUser, setSelectedCohortUser] = useState(null); @@ -478,7 +478,7 @@ function StudentReport() { } setCurrentProject({ ...task, status, file }); } catch (e) { - toast({ + createToast({ position: 'top', title: t('alert-message:review-url-error'), status: 'error', @@ -692,7 +692,7 @@ function StudentReport() { if (isWindow) { if (task.id) window.open(`/cohort/${cohortSlug}/student/${studentId}/assignment/${task.id}?academy=${academy}`); else { - toast({ + createToast({ position: 'top', title: t('no-task'), status: 'error', diff --git a/src/pages/syllabus/[cohortSlug]/[lesson]/[lessonSlug]/index.jsx b/src/pages/syllabus/[cohortSlug]/[lesson]/[lessonSlug]/index.jsx index bf170f358..ebfd0d2a2 100644 --- a/src/pages/syllabus/[cohortSlug]/[lesson]/[lessonSlug]/index.jsx +++ b/src/pages/syllabus/[cohortSlug]/[lesson]/[lessonSlug]/index.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'; import axios from 'axios'; import { Box, Flex, useDisclosure, Link, Avatar, - useColorModeValue, Modal, ModalOverlay, useToast, Tooltip, + useColorModeValue, Modal, ModalOverlay, Tooltip, ModalContent, ModalCloseButton, ModalBody, Button, } from '@chakra-ui/react'; import useTranslation from 'next-translate/useTranslation'; @@ -44,11 +44,12 @@ import { parseQuerys } from '../../../../../utils/url'; import completions from './completion-jobs.json'; import { generateUserContext } from '../../../../../utils/rigobotContext'; import SubTasks from '../../../../../common/components/MarkDownParser/SubTasks'; +import useCustomToast from '../../../../../common/hooks/useCustomToast'; function SyllabusContent() { const { t, lang } = useTranslation('syllabus'); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'ai-chat-access-error' }); const { isOpen, onToggle } = useDisclosure(); const { user, isLoading, isAuthenticatedWithRigobot } = useAuth(); @@ -300,7 +301,7 @@ function SyllabusContent() { plan: programSlug, }); router.push(`/${lang}/checkout${querys}`); - toast({ + createToast({ position: 'top', title: t('alert-message:access-denied'), status: 'error', @@ -761,7 +762,7 @@ function SyllabusContent() { } else setShowRigobotModal(true); } catch (e) { console.log(e); - toast({ + createToast({ position: 'top', title: t('alert-message:error-ai-chat'), status: 'error', diff --git a/src/pages/technology/[slug].jsx b/src/pages/technology/[slug].jsx index 8016d4c19..dd16a4ccd 100644 --- a/src/pages/technology/[slug].jsx +++ b/src/pages/technology/[slug].jsx @@ -1,6 +1,6 @@ import { useRouter } from 'next/router'; import { useState, useEffect, useRef } from 'react'; -import { Box, Flex, Container, Image, Button, useToast, useColorModeValue } from '@chakra-ui/react'; +import { Box, Flex, Container, Image, Button, useColorModeValue } from '@chakra-ui/react'; import Link from 'next/link'; import PropTypes from 'prop-types'; import useTranslation from 'next-translate/useTranslation'; @@ -19,6 +19,7 @@ import GridContainer from '../../common/components/GridContainer'; import MktEventCards from '../../common/components/MktEventCards'; import ProjectsLoader from '../../common/components/ProjectsLoader'; import { parseQuerys } from '../../utils/url'; +import useCustomToast from '../../common/hooks/useCustomToast'; let contentPerPage = 10; @@ -209,7 +210,7 @@ function LessonByTechnology({ assetData, technologyData, techsBySortPriority, co const [isAtEnd, setIsAtEnd] = useState(false); const [isAtStart, setIsAtStart] = useState(true); const router = useRouter(); - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'errors-no-data-error' }); const scrollRef = useRef(); const marketingInfoExist = Object.keys(marketingInfo).length > 0; const exercises = assetData?.filter((asset) => asset?.asset_type === 'EXERCISE'); @@ -285,7 +286,7 @@ function LessonByTechnology({ assetData, technologyData, techsBySortPriority, co useEffect(() => { if ((!technologyData?.slug || assetData?.length === 0)) { - toast({ + createToast({ position: 'top', title: t('errors.no-data'), status: 'error', diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index 4233e788c..d58810805 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -1,5 +1,5 @@ import { - Box, Button, Grid, useColorModeValue, useToast, Image, Avatar, Skeleton, Flex, + Box, Button, Grid, useColorModeValue, Image, Avatar, Skeleton, Flex, } from '@chakra-ui/react'; import { useEffect, useState, useContext } from 'react'; import { intervalToDuration, format } from 'date-fns'; @@ -34,6 +34,7 @@ import SmallCardsCarousel from '../../common/components/SmallCardsCarousel'; import LoaderScreen from '../../common/components/LoaderScreen'; import DynamicContentCard from '../../common/components/DynamicContentCard'; import { SessionContext } from '../../common/context/SessionContext'; +import useCustomToast from '../../common/hooks/useCustomToast'; const arrayOfImages = [ 'https://github-production-user-asset-6210df.s3.amazonaws.com/426452/264811559-ff8d2a4e-0a34-41c9-af90-57b0a96414b3.gif', @@ -170,7 +171,7 @@ function Workshop({ eventData, asset }) { const router = useRouter(); const { locale } = router; const eventSlug = router?.query?.event_slug; - const toast = useToast(); + const { createToast } = useCustomToast({ toastId: 'event-and-access-reservation' }); const { isAuthenticated, user } = useAuth(); const { featuredColor, hexColor } = useStyle(); const endDate = event?.ended_at || event?.ending_at; @@ -530,7 +531,7 @@ function Workshop({ eventData, asset }) { if (resp !== undefined) { setApplied(true); setIsCheckinModalOpen(true); - toast({ + createToast({ position: 'top', status: 'success', title: t('alert-message:success-event-reservation'), @@ -552,7 +553,7 @@ function Workshop({ eventData, asset }) { }, }); } else { - toast({ + createToast({ position: 'top', status: 'info', title: t('alert-message:event-access-error'), diff --git a/styles/globals.css b/styles/globals.css index 68b727c2d..ec394b444 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -555,6 +555,13 @@ body.chakra-ui-dark .anchorjs-link { .md-editor, .cm-theme, .md-editor-content-editor { height: 100% !important; } + +/* Esto elimina el max-width de las clases generadas por Chakra UI */ +.chakra-toast__inner { + width: 100vw; + max-width: 100vw !important; +} + /* body { overflow: auto !important; }