diff --git a/public/locales/en/dashboard.json b/public/locales/en/dashboard.json index 8b8a5453d..11643ac06 100644 --- a/public/locales/en/dashboard.json +++ b/public/locales/en/dashboard.json @@ -85,6 +85,9 @@ "get-more-mentorships": "Get more mentorships", "schedule-button": "Schedule a mentoring session", "mentors-available": "+{{count}} Mentors available", + "for": "for", + "service-not-found": "couldn't find service", + "mentor-not-found": "couldn't find mentor", "actionButtons": [ { "name": "mentoring", diff --git a/public/locales/en/workshops.json b/public/locales/en/workshops.json index 6515cfd43..7960726b3 100644 --- a/public/locales/en/workshops.json +++ b/public/locales/en/workshops.json @@ -14,6 +14,11 @@ "in-person-confirm": "This is an in-person event that will take place in {{address}}. Do you still want to confirm your attendance?", "confirm-attendance": "Yes, I will be there", "deny-attendance" : "No, I will not attend", + "denny-access":{ + "description": "This is a private event, only students with access to", + "button": "You don't have access to this event", + "can-join": "can join" + }, "form": { "title": "Join this event", "description": "Sign in to join other coders live solving technical or career challenges.", diff --git a/public/locales/es/dashboard.json b/public/locales/es/dashboard.json index d113d546e..f5ccaafca 100644 --- a/public/locales/es/dashboard.json +++ b/public/locales/es/dashboard.json @@ -85,6 +85,9 @@ "get-more-mentorships": "Consigue más mentorías", "schedule-button": "Programar una sesión de tutoría", "mentors-available": "+{{count}} Mentores disponibles", + "for": "para", + "service-not-found": "no se ha encontrado servicio", + "mentor-not-found": "no se ha encontrado el mentor", "actionButtons": [ { "name": "mentoring", diff --git a/public/locales/es/workshops.json b/public/locales/es/workshops.json index c0b1f1305..1c8ccb3a3 100644 --- a/public/locales/es/workshops.json +++ b/public/locales/es/workshops.json @@ -14,6 +14,11 @@ "in-person-confirm": "Este es un evento presencial que se llevará a cabo en {{address}}. ¿Aún quieres confirmar tu asistencia?", "confirm-attendance": "Si, si asistiré", "deny-attendance" : "No, no asistiré", + "denny-access":{ + "description": "Esto es un evento privado, solo estudiantes con acceso a", + "button": "No tienes acceso a este evento.", + "can-join": "pueden entrar" + }, "form": { "title": "Únete a este evento", "description": "Inicia sesión para unirte a otros programadores en vivo resolviendo desafíos técnicos o profesionales.", diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index a02592404..57fc097c0 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -7,12 +7,9 @@ import { // useToast, } from '@chakra-ui/react'; import PropTypes from 'prop-types'; -import { format } from 'date-fns'; -import { es } from 'date-fns/locale'; import { useRouter } from 'next/router'; import useTranslation from 'next-translate/useTranslation'; import bc from '../../services/breathecode'; -import MentoringFree from './MentoringFree'; import MentoringConsumables from './MentoringConsumables'; import useAuth from '../../hooks/useAuth'; import useCohortHandler from '../../hooks/useCohortHandler'; @@ -20,28 +17,19 @@ import useCohortHandler from '../../hooks/useCohortHandler'; function Mentoring({ width, allCohorts, allSyllabus, programServices, subscriptions, subscriptionData, }) { + // const toast = useToast(); const { t } = useTranslation('dashboard'); - const [savedChanges, setSavedChanges] = useState({}); + const router = useRouter(); + const { isLoading, user } = useAuth(); + const { slug } = router.query; const { state } = useCohortHandler(); const { cohortSession } = state; - const router = useRouter(); - const [consumables, setConsumables] = useState({}); + const [consumables, setConsumables] = useState([]); const [mentoryProps, setMentoryProps] = useState({}); const [allMentorsAvailable, setAllMentorsAvailable] = useState([]); const [programMentors, setProgramMentors] = useState([]); - const [isAvailableForConsumables, setIsAvailableForConsumables] = useState(true); - const { isLoading, user } = useAuth(); - // const toast = useToast(); - const { slug } = router.query; - - const [searchProps, setSearchProps] = useState({ - serviceSearch: '', - mentorSearch: '', - }); - - const servicesFiltered = programServices.list.filter( - (l) => l.name.toLowerCase().includes(searchProps.serviceSearch), - ); + const [cohortSessionIsSaaS, setCohortSessionIsSaaS] = useState(true); + const [searchProps, setSearchProps] = useState({ serviceSearch: '', mentorSearch: '' }); const filterServices = () => { if (subscriptionData?.selected_mentorship_service_set?.mentorship_services?.length > 0) { @@ -62,38 +50,13 @@ function Mentoring({ const mentorsFiltered = programMentors.filter( (mentor) => { const fullName = `${mentor.user.first_name} ${mentor.user.last_name}`.toLowerCase(); - const mentorServices = fullName.includes(searchProps.mentorSearch) && mentor.services.some((sv) => sv.status === 'ACTIVE' - && sv.slug === mentoryProps?.service?.slug); - return mentorServices; + return ( + fullName.includes(searchProps.mentorSearch) + && mentor.services.some((sv) => sv.status === 'ACTIVE' && sv.slug === mentoryProps?.service?.slug) + ); }, ); - const dateFormated = { - en: mentoryProps?.date && format(new Date(mentoryProps.date), 'MMMM dd'), - es: mentoryProps?.date && format(new Date(mentoryProps.date), "dd 'de' MMMM", { locale: es }), - }; - - const dateFormated2 = { - en: mentoryProps?.date && format(new Date(mentoryProps.date), 'MMMM dd, yyyy'), - es: mentoryProps?.date && format(new Date(mentoryProps.date), "dd 'de' MMMM, yyyy", { locale: es }), - }; - - useEffect(() => { - if (mentoryProps?.time) { - const [hours, minutes] = mentoryProps.time.split(':'); - - const nDate = mentoryProps?.date - && new Date(mentoryProps.date); - - nDate.setHours(+hours, +minutes, 0, 0); // set hours/minute; - setMentoryProps({ ...mentoryProps, date: nDate }); - setSavedChanges({ ...mentoryProps, date: nDate }); - } - }, [mentoryProps?.time]); - - const step1 = !mentoryProps?.service; - const step2 = mentoryProps?.service && !mentoryProps?.date; - const getAllMentorsAvailable = async () => { const servicesSlugs = programServices.list.map((service) => service?.slug); @@ -106,7 +69,6 @@ function Mentoring({ academies[academy.id].services.push(restOfService); }); - // Convert the object to an array of academies with their services const academyData = Object.entries(academies).map(([academy, values]) => ({ id: Number(academy), services: values.services, @@ -130,6 +92,21 @@ function Mentoring({ return []; }; + const sortByConsumptionAvailability = (allConsumables) => allConsumables.sort((a, b) => { + const balanceA = a?.balance?.unit; + const balanceB = b?.balance?.unit; + + if (balanceA === -1 && balanceB !== -1) return -1; + if (balanceA !== -1 && balanceB === -1) return 1; + + if (balanceA > 0 && balanceB <= 0) return -1; + if (balanceA <= 0 && balanceB > 0) return 1; + + if (balanceA > 0 && balanceB > 0) return balanceB - balanceA; + + return 0; + }); + const getMentorsAndConsumables = async () => { const mentors = await getAllMentorsAvailable(); const reqConsumables = await bc.payment().service().consumable() @@ -141,7 +118,8 @@ function Mentoring({ })))); const allConsumables = await Promise.all(reqConsumables); - setConsumables(allConsumables); + const sortedConsumables = sortByConsumptionAvailability(allConsumables); + setConsumables(sortedConsumables); setAllMentorsAvailable(mentors); }; @@ -153,73 +131,34 @@ function Mentoring({ useEffect(() => { const existsCohortSession = typeof cohortSession?.available_as_saas === 'boolean'; - if (existsCohortSession) { - setIsAvailableForConsumables(cohortSession?.available_as_saas); - } - if (!existsCohortSession) { - if (allCohorts.length > 0) { - setIsAvailableForConsumables(allCohorts?.some((c) => c.cohort?.available_as_saas === true)); - } + setCohortSessionIsSaaS(cohortSession?.available_as_saas); } }, [allCohorts]); - const mentorshipService = consumables?.mentorship_service_sets?.find( - (c) => c?.slug.toLowerCase() === subscriptionData?.selected_mentorship_service_set?.slug.toLowerCase(), - ); - return !isLoading && user?.id && ( {t('supportSideBar.mentoring-label')} - {isAvailableForConsumables ? ( - 0 ? programServices.list : subscriptionData?.selected_mentorship_service_set?.mentorship_services, - servicesFiltered: suscriptionServicesFiltered, - dateFormated, - searchProps, - setSearchProps, - setProgramMentors, - savedChanges, - setSavedChanges, - mentorsFiltered, - step1, - step2, - dateFormated2, - allMentorsAvailable, - subscriptionData, - allSubscriptions: subscriptions, - }} - /> - ) : ( - - )} + 0 ? programServices.list : subscriptionData?.selected_mentorship_service_set?.mentorship_services, + servicesFiltered: suscriptionServicesFiltered, + searchProps, + setSearchProps, + setProgramMentors, + mentorsFiltered, + allMentorsAvailable, + subscriptionData, + cohortSessionIsSaaS, + allSubscriptions: subscriptions, + }} + /> ); } diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 3f8eb7479..fddb8b96e 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -18,7 +18,7 @@ import Text from '../Text'; import { AvatarSkeletonWrapped } from '../Skeleton'; import modifyEnv from '../../../../modifyEnv'; import { validatePlanExistence } from '../../handlers/subscriptions'; -import { getStorageItem, isDevMode } from '../../../utils'; +import { getStorageItem } from '../../../utils'; import { reportDatalayer } from '../../../utils/requests'; function NoConsumablesCard({ t, setMentoryProps, handleGetMoreMentorships, mentoryProps, subscriptionData, disableBackButton = false, ...rest }) { @@ -53,9 +53,9 @@ function NoConsumablesCard({ t, setMentoryProps, handleGetMoreMentorships, mento {!disableBackButton && ( - + )} ); @@ -90,13 +90,12 @@ function ProfilesSection({ } function MentoringConsumables({ - mentoryProps, width, consumables, mentorshipService, setMentoryProps, - programServices, dateFormated, servicesFiltered, searchProps, - setSearchProps, setProgramMentors, savedChanges, setSavedChanges, - mentorsFiltered, dateFormated2, allMentorsAvailable, subscriptionData, allSubscriptions, + mentoryProps, width, consumables, cohortSessionIsSaaS, setMentoryProps, + programServices, servicesFiltered, searchProps, setSearchProps, setProgramMentors, + mentorsFiltered, allMentorsAvailable, subscriptionData, allSubscriptions, + queryService, queryMentor, titleSize, }) { const { t } = useTranslation('dashboard'); - const { user } = useAuth(); const BREATHECODE_HOST = modifyEnv({ queryString: 'host', env: process.env.BREATHECODE_HOST }); const commonBackground = useColorModeValue('white', 'rgba(255, 255, 255, 0.1)'); @@ -108,29 +107,32 @@ function MentoringConsumables({ const [isFetchingDataForModal, setIsFetchingDataForModal] = useState(false); const [dataToGetAccessModal, setDataToGetAccessModal] = useState({}); const [consumableOfService, setConsumableOfService] = useState({}); + const [servicesWithMentorsAvailable, setServicesWithMentorsAvailable] = useState([]); + const [hasReset, setHasReset] = useState(false); + const [notifyError, setNotifyError] = useState(true); + const [shouldHandleService, setShouldHandleService] = useState(true); const router = useRouter(); - const toast = useToast(); const { slug } = router.query; - - const mentorshipBalance = mentorshipService?.balance?.unit || mentorshipService?.balance || consumableOfService?.balance?.unit; + const toast = useToast(); + const mentorshipBalance = consumableOfService?.balance?.unit; const currentBalance = Number(mentorshipBalance && mentorshipBalance); const calculateExistenceOfConsumable = () => { if (consumableOfService.available_as_saas === false) return true; if (consumableOfService?.balance) return consumableOfService?.balance?.unit > 0 || consumableOfService?.balance?.unit === -1; - return consumables?.mentorship_service_sets?.length > 0 && Object.values(mentorshipService).length > 0 && (currentBalance > 0 || currentBalance === -1); + return consumables?.mentorship_service_sets?.length > 0 && (currentBalance > 0 || currentBalance === -1); }; const existConsumablesOnCurrentService = calculateExistenceOfConsumable(); const getMostRecentPaidAt = (invoices) => invoices.reduce((latest, invoice) => { const paidAtDate = new Date(invoice.paid_at); return paidAtDate > latest ? paidAtDate : latest; - }, new Date(0)); // Initialize with a very old date + }, new Date(0)); const sortByMostRecentInvoice = (a, b) => { const latestA = getMostRecentPaidAt(a.invoices); const latestB = getMostRecentPaidAt(b.invoices); - return latestB - latestA; // Descending order + return latestB - latestA; }; const currentServiceSubscription = Array.isArray(allSubscriptions) && allSubscriptions.sort(sortByMostRecentInvoice).find((subscription) => subscription.selected_mentorship_service_set.mentorship_services.some((service) => service.slug === mentoryProps?.service?.slug)); @@ -144,7 +146,7 @@ function MentoringConsumables({ } }, [allMentorsAvailable]); - const manageMentorsData = (service, data) => { + const manageMentorsData = (service, mentors) => { reportDatalayer({ dataLayer: { event: 'select_mentorship_service', @@ -153,18 +155,18 @@ function MentoringConsumables({ mentorship_service: service?.slug, }, }); - const relatedConsumables = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); - setProgramMentors(data); + const relatedConsumable = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); + setProgramMentors(mentors); setConsumableOfService({ - ...relatedConsumables, + ...relatedConsumable, balance: { - unit: service?.academy?.available_as_saas === false ? -1 : relatedConsumables?.balance?.unit, + unit: (service?.academy?.available_as_saas === false || cohortSessionIsSaaS === false) ? -1 : relatedConsumable?.balance?.unit, }, available_as_saas: service?.academy?.available_as_saas, }); + setTimeout(() => { setMentoryProps({ ...mentoryProps, service }); - setSavedChanges({ ...savedChanges, service }); }, 50); }; @@ -194,7 +196,68 @@ function MentoringConsumables({ } }; - const servicesWithMentorsAvailable = servicesFiltered.filter((service) => allMentorsAvailable.some((mentor) => mentor.services.some((mentServ) => mentServ.slug === service.slug))); + useEffect(() => { + const getAllServicesWithMentors = () => servicesFiltered.filter((service) => allMentorsAvailable.some((ment) => ment.services.some((mentServ) => mentServ.slug === service.slug))); + const getServicesWithMentor = (mentor) => servicesFiltered.filter((service) => mentor.services.some((mentServ) => mentServ.slug === service.slug)); + + const showErrorToast = () => { + toast({ + position: 'top', + title: 'Error', + description: `${t('supportSideBar.mentor-not-found')} "${queryMentor}"`, + status: 'error', + duration: 7000, + isClosable: true, + }); + }; + + let servWithMentorsAvailable = getAllServicesWithMentors(); + + if (queryMentor && allMentorsAvailable.length > 0 && !hasReset) { + const mentorFound = allMentorsAvailable.find((ment) => ment.slug === queryMentor); + + if (!mentorFound && notifyError) { + showErrorToast(); + setNotifyError(false); + } + if (mentorFound) servWithMentorsAvailable = getServicesWithMentor(mentorFound); + } + + setServicesWithMentorsAvailable(servWithMentorsAvailable); + + if (!hasReset && queryMentor) { + setOpen(true); + } + }, [servicesFiltered, queryMentor, hasReset]); + + useEffect(() => { + if (queryService && servicesWithMentorsAvailable?.length > 0 && shouldHandleService && !hasReset) { + const serviceFound = servicesWithMentorsAvailable.find((service) => service.slug === queryService); + + if (!serviceFound && notifyError) { + toast({ + position: 'top', + title: 'Error', + description: `${t('supportSideBar.service-not-found')} "${queryService}" ${queryMentor ? `${t('supportSideBar.for')} "${queryMentor}"` : ''}`, + status: 'error', + duration: 7000, + isClosable: true, + }); + setNotifyError(false); + return; + } + + handleService(serviceFound); + setOpen(true); + setShouldHandleService(false); + } + }, [hasReset, servicesWithMentorsAvailable]); + + const reset = () => { + if (mentoryProps?.service) setMentoryProps({}); + else setOpen(false); + setHasReset(true); + }; const handleGetMoreMentorships = () => { setIsFetchingDataForModal(true); @@ -212,16 +275,17 @@ function MentoringConsumables({ }) .finally(() => setIsFetchingDataForModal(false)); }; - const reportBookMentor = () => { + + const reportBookMentor = (mentorSelected) => { reportDatalayer({ dataLayer: { event: 'book_mentorship_session', path: router.pathname, consumables_amount: currentBalance, mentorship_service: mentoryProps?.service?.slug, - mentor_name: `${mentoryProps.mentor.user.first_name} ${mentoryProps.mentor.user.last_name}`, - mentor_id: mentoryProps.mentor.slug, - mentor_booking_url: mentoryProps.mentor.booking_url, + mentor_name: `${mentorSelected.user.first_name} ${mentorSelected.user.last_name}`, + mentor_id: mentorSelected.slug, + mentor_booking_url: mentorSelected.booking_url, }, }); }; @@ -236,12 +300,12 @@ function MentoringConsumables({ > {open && mentoryProps?.service && ( - setMentoryProps({})} cursor="pointer"> + )} {open && !mentoryProps?.service && ( - setOpen(false)} cursor="pointer"> + )} @@ -249,7 +313,7 @@ function MentoringConsumables({ {!mentoryProps?.service && (consumables?.mentorship_service_sets?.length !== 0 || currentBalance !== 0) && ( <> - + {t('supportSideBar.mentoring')}
@@ -285,11 +349,10 @@ function MentoringConsumables({ )} )} - - {t('supportSideBar.mentors-available', { count: 3 })} + + {t('supportSideBar.mentors-available', { count: allMentorsAvailable.length })}
- {/* Schedule event */} - )} - {mentoryProps?.confirm && ( - + {mentoryProps?.service && !mentoryProps?.mentor && ( + <> + + setSearchProps({ ...searchProps, mentorSearch: e.target.value?.toLowerCase() })} background={commonBackground} borderBottomRadius="0" border="0" placeholder={t('supportSideBar.search-mentor')} /> + + + + + + {mentorsFiltered.length > 0 ? mentorsFiltered.map((mentor, i) => ( + + {i !== 0 && ( + )} - {!mentoryProps?.confirm && ( - setMentoryProps({ ...mentoryProps, time: null })} className="link" width="fit-content" margin="0 auto"> - Go back + + {`${mentor?.user?.first_name} + + + {`${mentor.user.first_name} ${mentor.user.last_name}`} + + + + {(mentor.one_line_bio && mentor.one_line_bio !== '') ? `${mentor.one_line_bio} ` : ''} + {mentor?.booking_url ? ( + reportBookMentor(mentor)} + href={`${BREATHECODE_HOST}/mentor/${mentor?.slug}?utm_campaign=${mentoryProps?.service?.slug}&utm_source=4geeks&salesforce_uuid=${user?.id}&token=${accessToken}`} + target="_blank" + rel="noopener noreferrer" + > + {t('supportSideBar.create-session-text')} + + ) : ( + + {t('supportSideBar.no-mentor-link')} + + )} + - )} + + + )) : ( + + {t('supportSideBar.no-mentors')} - - )} + )} +
)} @@ -519,30 +504,30 @@ function MentoringConsumables({ MentoringConsumables.propTypes = { mentoryProps: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])), width: PropTypes.string, + titleSize: PropTypes.string, + queryService: PropTypes.string, + queryMentor: PropTypes.string, consumables: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any])), - mentorshipService: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any])), setMentoryProps: PropTypes.func.isRequired, programServices: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])), - dateFormated: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])).isRequired, servicesFiltered: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])).isRequired, searchProps: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])).isRequired, setSearchProps: PropTypes.func.isRequired, - savedChanges: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])).isRequired, - setSavedChanges: PropTypes.func.isRequired, setProgramMentors: PropTypes.func, mentorsFiltered: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.any])).isRequired, - dateFormated2: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any])).isRequired, subscriptionData: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any])), allSubscriptions: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.any])), }; MentoringConsumables.defaultProps = { + queryService: undefined, + queryMentor: undefined, mentoryProps: [], width: '100%', + titleSize: '14px', consumables: {}, - mentorshipService: {}, programServices: [], - setProgramMentors: () => {}, + setProgramMentors: () => { }, subscriptionData: {}, allSubscriptions: [], }; diff --git a/src/pages/choose-program/index.jsx b/src/pages/choose-program/index.jsx index 1223806e6..31af72165 100644 --- a/src/pages/choose-program/index.jsx +++ b/src/pages/choose-program/index.jsx @@ -29,6 +29,7 @@ import ReactPlayerV2 from '../../common/components/ReactPlayerV2'; import useStyle from '../../common/hooks/useStyle'; import SupportSidebar from '../../common/components/SupportSidebar'; import Feedback from '../../common/components/Feedback'; +import axios from '../../axios'; import LanguageSelector from '../../common/components/LanguageSelector'; export const getStaticProps = async ({ locale, locales }) => { @@ -124,6 +125,7 @@ function chooseProgram() { const getServices = async (userRoles) => { if (userRoles?.length > 0) { + delete axios.defaults.headers.common.Academy; const mentorshipPromises = await userRoles.map((role) => bc.mentorship({ academy: role?.academy?.id }, true).getService() .then((resp) => { const data = resp?.data; diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index d5da6fbc0..e910cf61f 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -166,6 +166,7 @@ function Page({ eventData, asset }) { const [dataToGetAccessModal, setDataToGetAccessModal] = useState({}); const [isFetchingDataForModal, setIsFetchingDataForModal] = useState(false); const [noConsumablesFound, setNoConsumablesFound] = useState(false); + const [denyAccessToEvent, setDenyAccessToEvent] = useState(false); const router = useRouter(); const { locale } = router; @@ -350,9 +351,36 @@ function Page({ eventData, asset }) { }); }; + const sortByConsumptionAvailability = (consum) => consum.sort((a, b) => { + const balanceA = a?.balance?.unit; + const balanceB = b?.balance?.unit; + + if (balanceA === -1 && balanceB !== -1) return -1; + if (balanceA !== -1 && balanceB === -1) return 1; + + if (balanceA > 0 && balanceB <= 0) return -1; + if (balanceA <= 0 && balanceB > 0) return 1; + + return 0; + }); + + const getSubscriptionForCurrentEvent = () => { + if (!subscriptions || !event?.event_type?.slug) return []; + const currentEventSlug = event.event_type.slug; + + const filteredSubscriptions = subscriptions.filter((subscription) => { + const eventTypes = subscription.selected_event_type_set?.event_types || []; + return eventTypes.some((eventType) => eventType.slug === currentEventSlug); + }); + + return filteredSubscriptions; + }; + const consumableEventList = consumables?.data?.event_type_sets || []; - const currentConsumable = consumableEventList?.length > 0 ? consumableEventList?.find( - (c) => subscriptions.some( + const availableConsumables = sortByConsumptionAvailability(consumableEventList); + const subscriptionsForCurrentEvent = getSubscriptionForCurrentEvent(); + const currentConsumable = availableConsumables?.length > 0 ? availableConsumables?.find( + (c) => subscriptionsForCurrentEvent.some( (s) => c?.slug.toLowerCase() === s?.selected_event_type_set?.slug.toLowerCase(), ), ) : {}; @@ -362,6 +390,11 @@ function Page({ eventData, asset }) { const existsNoAvailableAsSaas = myCohorts.some((c) => c?.cohort?.available_as_saas === false); const isFreeForConsumables = event?.free_for_all || finishedEvent || (event?.free_for_bootcamps === true && existsNoAvailableAsSaas); + useEffect(() => { + if (subscriptionsForCurrentEvent.length === 0) setDenyAccessToEvent(true); + else setDenyAccessToEvent(false); + }, [subscriptionsForCurrentEvent]); + const dynamicFormInfo = () => { if (finishedEvent) { return ({ @@ -374,7 +407,7 @@ function Page({ eventData, asset }) { title: '', childrenDescription: ( - {t('no-consumables.description')} + {!denyAccessToEvent ? t('no-consumables.description') : `${t('denny-access.description')} '${event?.event_type?.name}' ${t('denny-access.can-join')}`} ), }); @@ -876,7 +909,7 @@ function Page({ eventData, asset }) { {hasFetchedAndNoConsumablesToUse && ( - {t('no-consumables.description')} + {!denyAccessToEvent ? t('no-consumables.description') : `${t('denny-access.description')} '${event?.event_type?.name}' ${t('denny-access.can-join')}`} )} )} @@ -1028,10 +1062,11 @@ function Page({ eventData, asset }) { alignItems="center" gridGap="10px" width="100%" + isDisabled={denyAccessToEvent} background={hexColor.greenLight} > - {t('no-consumables.get-more-workshops')} - + {!denyAccessToEvent ? t('no-consumables.get-more-workshops') : t('denny-access.button')} + {!denyAccessToEvent && }
) : ( diff --git a/src/utils/index.js b/src/utils/index.js index 009194169..088479a7a 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -32,24 +32,24 @@ const slugify = (str) => (typeof str === 'string' ? str .replace(/^-+|-+$/g, '') : ''); - const unSlugify = (str, capitalize = false) => (typeof str === 'string' - ? str - .replace(/-/g, ' ') - .replace( - /\w\S*/g, - (txt) => { - const firstLetter = capitalize ? txt.charAt(0).toUpperCase() : txt.charAt(0); - return firstLetter + txt.substring(1).toLowerCase(); - }, - ) - : ''); +const unSlugify = (str, capitalize = false) => (typeof str === 'string' + ? str + .replace(/-/g, ' ') + .replace( + /\w\S*/g, + (txt) => { + const firstLetter = capitalize ? txt.charAt(0).toUpperCase() : txt.charAt(0); + return firstLetter + txt.substring(1).toLowerCase(); + }, + ) + : ''); const unSlugifyCapitalize = (str) => (typeof str === 'string' ? str .replace(/-/g, ' ') .replace( -/\w\S*/g, - (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase(), -) + /\w\S*/g, + (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase(), + ) : ''); function slugToTitle(slug) { @@ -60,7 +60,7 @@ function slugToTitle(slug) { return word.charAt(0) + word.slice(1); }, ).join(' ').replace(/([A-Z])/g, ' $1') - .trim(); + .trim(); } const cleanQueryStrings = (url) => url.split('?')[0]; @@ -116,8 +116,8 @@ const devLog = (msg, ...params) => { // Relevant logs only in dev mode const devLogTable = (msg, array) => { // Relevant table logs with title only in dev mode if (isDevMode) { console.group(); - console.log(`%c🛠️${msg}`, 'font-size: 14px'); - console.table(array); + console.log(`%c🛠️${msg}`, 'font-size: 14px'); + console.table(array); console.groupEnd(); } }; @@ -127,19 +127,19 @@ const objectAreNotEqual = (t1, t2) => Object.keys(t1).map((l) => t1[l] === t2[l] function removeURLParameter(url, parameter) { const urlparts = url.split('?'); if (urlparts.length >= 2) { - const prefix = `${encodeURIComponent(parameter)}=`; - const pars = urlparts[1].split(/[&;]/g); - - // reverse iteration as may be destructive - // eslint-disable-next-line no-plusplus - for (let i = pars.length; i-- > 0;) { - // idiom for string.startsWith - if (pars[i].lastIndexOf(prefix, 0) !== -1) { - pars.splice(i, 1); - } + const prefix = `${encodeURIComponent(parameter)}=`; + const pars = urlparts[1].split(/[&;]/g); + + // reverse iteration as may be destructive + // eslint-disable-next-line no-plusplus + for (let i = pars.length; i-- > 0;) { + // idiom for string.startsWith + if (pars[i].lastIndexOf(prefix, 0) !== -1) { + pars.splice(i, 1); } + } - return urlparts[0] + (pars.length > 0 ? `?${pars.join('&')}` : ''); + return urlparts[0] + (pars.length > 0 ? `?${pars.join('&')}` : ''); } return url; } @@ -297,7 +297,7 @@ const getQueryString = (key, def) => { const createArray = (length) => Array.from({ length }, (_, i) => i); const lengthOfString = (string) => (typeof string === 'string' ? string?.replaceAll(/\s/g, '').length : 0); -const syncInterval = (callback = () => {}) => { +const syncInterval = (callback = () => { }) => { const now = new Date(); const secondsToNextMinute = 60 - now.getSeconds(); @@ -358,7 +358,7 @@ function adjustNumberBeetwenMinMax({ number = 1, min = 1, max = 10 }) { function getDiscountedPrice({ numItems, maxItems, discountRatio, bundleSize, pricePerUnit, startDiscountFrom = 0 }) { if (numItems > maxItems) { - console.log('numItems cannot be greater than maxItems'); + console.log('numItems cannot be greater than maxItems'); } let totalDiscountRatio = 0; @@ -367,12 +367,12 @@ function getDiscountedPrice({ numItems, maxItems, discountRatio, bundleSize, pri const maxDiscount = 0.2; for (let i = startDiscountFrom; i < Math.floor(numItems / bundleSize); i += 1) { - totalDiscountRatio += currentDiscountRatio; - currentDiscountRatio -= currentDiscountRatio * discountNerf; + totalDiscountRatio += currentDiscountRatio; + currentDiscountRatio -= currentDiscountRatio * discountNerf; } if (totalDiscountRatio > maxDiscount) { - totalDiscountRatio = maxDiscount; + totalDiscountRatio = maxDiscount; } const amount = pricePerUnit * numItems; @@ -412,11 +412,11 @@ function cleanObject(obj) { function decodeBase64(encoded) { // Decode from base64 and convert to UTF-8 and remove � characters if they exist - const decoded = new TextDecoder('utf-8') - .decode(Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0))) - .replace(/�/g, ''); + const decoded = new TextDecoder('utf-8') + .decode(Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0))) + .replace(/�/g, ''); - return decoded; + return decoded; } export {