From 7b6c9cf7584828195219d819aa3d7186344e8b50 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Mon, 26 Aug 2024 16:10:13 -0400 Subject: [PATCH 01/12] :bug: fix1 when user in basic plan run out of consumables and then upgrade plan, consumables use will be the one's from the paid plan --- src/common/components/SupportSidebar/Mentoring.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index a02592404..fabcbcc6f 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -140,7 +140,10 @@ function Mentoring({ ...mentorshipServiceSet, })))); - const allConsumables = await Promise.all(reqConsumables); + let allConsumables = await Promise.all(reqConsumables); + if (allConsumables.length > 1) { + allConsumables = allConsumables.filter((consumable) => consumable?.balance?.unit !== 0); + } setConsumables(allConsumables); setAllMentorsAvailable(mentors); }; From 3f19ba4f20f730caded4be9b1e66329e3e2d40fe Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Thu, 29 Aug 2024 17:31:17 -0400 Subject: [PATCH 02/12] :bug: user will get its consumables if needed and has them --- .../components/SupportSidebar/Mentoring.jsx | 9 +- src/pages/workshops/[event_slug].jsx | 5 +- src/utils/index.js | 82 ++++++++++--------- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index fabcbcc6f..b2972e2f8 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -16,6 +16,7 @@ import MentoringFree from './MentoringFree'; import MentoringConsumables from './MentoringConsumables'; import useAuth from '../../hooks/useAuth'; import useCohortHandler from '../../hooks/useCohortHandler'; +import { checkForConsumablesAvailable } from '../../../utils'; function Mentoring({ width, allCohorts, allSyllabus, programServices, subscriptions, subscriptionData, @@ -140,11 +141,9 @@ function Mentoring({ ...mentorshipServiceSet, })))); - let allConsumables = await Promise.all(reqConsumables); - if (allConsumables.length > 1) { - allConsumables = allConsumables.filter((consumable) => consumable?.balance?.unit !== 0); - } - setConsumables(allConsumables); + const allConsumables = await Promise.all(reqConsumables); + const validConsumables = checkForConsumablesAvailable(allConsumables); + setConsumables(validConsumables); setAllMentorsAvailable(mentors); }; diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index d5da6fbc0..52be11673 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -14,7 +14,7 @@ import SimpleModal from '../../common/components/SimpleModal'; import GridContainer from '../../common/components/GridContainer'; import Heading from '../../common/components/Heading'; import Text from '../../common/components/Text'; -import { adjustNumberBeetwenMinMax, capitalizeFirstLetter, getStorageItem, isValidDate } from '../../utils'; +import { adjustNumberBeetwenMinMax, capitalizeFirstLetter, getStorageItem, isValidDate, checkForConsumablesAvailable } from '../../utils'; import useStyle from '../../common/hooks/useStyle'; import Icon from '../../common/components/Icon'; import PublicProfile from '../../common/components/PublicProfile'; @@ -351,7 +351,8 @@ function Page({ eventData, asset }) { }; const consumableEventList = consumables?.data?.event_type_sets || []; - const currentConsumable = consumableEventList?.length > 0 ? consumableEventList?.find( + const availableConsumables = checkForConsumablesAvailable(consumableEventList); + const currentConsumable = availableConsumables?.length > 0 ? availableConsumables?.find( (c) => subscriptions.some( (s) => c?.slug.toLowerCase() === s?.selected_event_type_set?.slug.toLowerCase(), ), diff --git a/src/utils/index.js b/src/utils/index.js index 21a17920e..cfc288c25 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(); @@ -348,7 +348,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; @@ -357,12 +357,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; @@ -402,11 +402,17 @@ 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; +function checkForConsumablesAvailable(consumables) { + const consumablesAvailable = consumables.filter((consumable) => consumable?.balance?.unit !== 0); + if (consumablesAvailable.length > 0) return consumablesAvailable; + return consumables; } export { @@ -419,5 +425,5 @@ export { sortToNearestTodayDate, isNumber, isDateMoreThanAnyDaysAgo, getQueryString, isValidDate, createArray, url, lengthOfString, syncInterval, getBrowserSize, calculateDifferenceDays, capitalizeFirstLetter, adjustNumberBeetwenMinMax, getDiscountedPrice, formatPrice, cleanObject, slugToTitle, decodeBase64, - removeSessionStorageItem, + removeSessionStorageItem, checkForConsumablesAvailable, }; From b5ecbf4d4700e8ac09a36a6f0166a36c64359955 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Thu, 29 Aug 2024 21:15:28 -0400 Subject: [PATCH 03/12] :recycle: refactor mentorshipService (was not getting info at all) more refactor to be done --- src/common/components/SupportSidebar/Mentoring.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index b2972e2f8..eb05595de 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -155,7 +155,6 @@ function Mentoring({ useEffect(() => { const existsCohortSession = typeof cohortSession?.available_as_saas === 'boolean'; - if (existsCohortSession) { setIsAvailableForConsumables(cohortSession?.available_as_saas); } @@ -166,9 +165,11 @@ function Mentoring({ } }, [allCohorts]); - const mentorshipService = consumables?.mentorship_service_sets?.find( - (c) => c?.slug.toLowerCase() === subscriptionData?.selected_mentorship_service_set?.slug.toLowerCase(), - ); + const mentorshipService = consumables?.length > 0 ? consumables?.find( + (c) => subscriptions.some( + (s) => c?.slug.toLowerCase() === s?.selected_mentorship_service_set?.slug.toLowerCase(), + ), + ) : {}; return !isLoading && user?.id && ( From 1494445a73c6c8ffd08c82c5251459adf970e795 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Mon, 9 Sep 2024 20:35:33 -0400 Subject: [PATCH 04/12] :recycle: refactor of the code, sort consumables to avoid bug avoid user access to workshop if not subscribed --- public/locales/en/workshops.json | 5 ++ public/locales/es/workshops.json | 5 ++ .../components/SupportSidebar/Mentoring.jsx | 18 +++++- .../SupportSidebar/MentoringConsumables.jsx | 19 +++++- src/pages/workshops/[event_slug].jsx | 59 ++++++++++++++++--- src/utils/index.js | 8 +-- 6 files changed, 92 insertions(+), 22 deletions(-) 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/workshops.json b/public/locales/es/workshops.json index c0b1f1305..dcf0cb3ff 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": "", + "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 eb05595de..c900a2e88 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -16,7 +16,6 @@ import MentoringFree from './MentoringFree'; import MentoringConsumables from './MentoringConsumables'; import useAuth from '../../hooks/useAuth'; import useCohortHandler from '../../hooks/useCohortHandler'; -import { checkForConsumablesAvailable } from '../../../utils'; function Mentoring({ width, allCohorts, allSyllabus, programServices, subscriptions, subscriptionData, @@ -131,6 +130,19 @@ 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; + + return 0; + }); + const getMentorsAndConsumables = async () => { const mentors = await getAllMentorsAvailable(); const reqConsumables = await bc.payment().service().consumable() @@ -142,8 +154,8 @@ function Mentoring({ })))); const allConsumables = await Promise.all(reqConsumables); - const validConsumables = checkForConsumablesAvailable(allConsumables); - setConsumables(validConsumables); + const sortedConsumables = sortByConsumptionAvailability(allConsumables); + setConsumables(sortedConsumables); setAllMentorsAvailable(mentors); }; diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 3f8eb7479..5d054dcbc 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -144,6 +144,18 @@ function MentoringConsumables({ } }, [allMentorsAvailable]); + const checkForConsumableAvailable = (consumableList, serviceSelected) => { + const filteredConsumables = consumableList.filter((consumable) => consumable?.mentorship_services?.some((service) => serviceSelected?.slug === service.slug)); + + const validConsumable = filteredConsumables.find((consumable) => consumable?.balance?.unit === -1 || consumable?.balance?.unit > 0); + + if (validConsumable) { + return validConsumable; + } + const balanceZeroConsumable = filteredConsumables.find((consumable) => consumable?.balance?.unit === 0); + return balanceZeroConsumable; + }; + const manageMentorsData = (service, data) => { reportDatalayer({ dataLayer: { @@ -153,12 +165,13 @@ function MentoringConsumables({ mentorship_service: service?.slug, }, }); - const relatedConsumables = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); + const relatedConsumable = checkForConsumableAvailable(consumables, service); + setProgramMentors(data); setConsumableOfService({ - ...relatedConsumables, + ...relatedConsumable, balance: { - unit: service?.academy?.available_as_saas === false ? -1 : relatedConsumables?.balance?.unit, + unit: service?.academy?.available_as_saas === false ? -1 : relatedConsumable?.balance?.unit, }, available_as_saas: service?.academy?.available_as_saas, }); diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index 52be11673..338a7a609 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -14,7 +14,7 @@ import SimpleModal from '../../common/components/SimpleModal'; import GridContainer from '../../common/components/GridContainer'; import Heading from '../../common/components/Heading'; import Text from '../../common/components/Text'; -import { adjustNumberBeetwenMinMax, capitalizeFirstLetter, getStorageItem, isValidDate, checkForConsumablesAvailable } from '../../utils'; +import { adjustNumberBeetwenMinMax, capitalizeFirstLetter, getStorageItem, isValidDate } from '../../utils'; import useStyle from '../../common/hooks/useStyle'; import Icon from '../../common/components/Icon'; import PublicProfile from '../../common/components/PublicProfile'; @@ -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,10 +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 availableConsumables = checkForConsumablesAvailable(consumableEventList); + const availableConsumables = sortByConsumptionAvailability(consumableEventList); + const subscriptionsForCurrentEvent = getSubscriptionForCurrentEvent(); const currentConsumable = availableConsumables?.length > 0 ? availableConsumables?.find( - (c) => subscriptions.some( + (c) => subscriptionsForCurrentEvent.some( (s) => c?.slug.toLowerCase() === s?.selected_event_type_set?.slug.toLowerCase(), ), ) : {}; @@ -363,6 +390,18 @@ 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); + console.log('AAAAAAAAAA', availableConsumables); + console.log('CURRENT CONSUMABLE', currentConsumable); + console.log('suscription for current event', subscriptionsForCurrentEvent); + console.log('SUSCRIPCIONT', subscriptions); + + useEffect(() => { + if (subscriptionsForCurrentEvent.length === 0) setDenyAccessToEvent(true); + else { + setDenyAccessToEvent(false); + } + }, [subscriptionsForCurrentEvent]); + const dynamicFormInfo = () => { if (finishedEvent) { return ({ @@ -375,7 +414,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')}`} ), }); @@ -877,7 +916,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')}`} )} )} @@ -1029,10 +1069,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 cfc288c25..5237ec8e2 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -409,12 +409,6 @@ function decodeBase64(encoded) { return decoded; } -function checkForConsumablesAvailable(consumables) { - const consumablesAvailable = consumables.filter((consumable) => consumable?.balance?.unit !== 0); - if (consumablesAvailable.length > 0) return consumablesAvailable; - return consumables; -} - export { isWindow, assetTypeValues, HAVE_SESSION, slugify, unSlugify, unSlugifyCapitalize, location, isPlural, getStorageItem, includesToLowerCase, getExtensionName, @@ -425,5 +419,5 @@ export { sortToNearestTodayDate, isNumber, isDateMoreThanAnyDaysAgo, getQueryString, isValidDate, createArray, url, lengthOfString, syncInterval, getBrowserSize, calculateDifferenceDays, capitalizeFirstLetter, adjustNumberBeetwenMinMax, getDiscountedPrice, formatPrice, cleanObject, slugToTitle, decodeBase64, - removeSessionStorageItem, checkForConsumablesAvailable, + removeSessionStorageItem, }; From 4ac48447d83ab639aac268f913f7e4a8924930d5 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Tue, 10 Sep 2024 14:48:14 -0400 Subject: [PATCH 05/12] :recycle: refactor of small pieces of code --- public/locales/es/workshops.json | 2 +- .../SupportSidebar/MentoringConsumables.jsx | 23 ++++--------------- src/pages/workshops/[event_slug].jsx | 5 ---- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/public/locales/es/workshops.json b/public/locales/es/workshops.json index dcf0cb3ff..1c8ccb3a3 100644 --- a/public/locales/es/workshops.json +++ b/public/locales/es/workshops.json @@ -15,7 +15,7 @@ "confirm-attendance": "Si, si asistiré", "deny-attendance" : "No, no asistiré", "denny-access":{ - "description": "", + "description": "Esto es un evento privado, solo estudiantes con acceso a", "button": "No tienes acceso a este evento.", "can-join": "pueden entrar" }, diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 5d054dcbc..46eea4c96 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -53,9 +53,9 @@ function NoConsumablesCard({ t, setMentoryProps, handleGetMoreMentorships, mento {!disableBackButton && ( - + )} ); @@ -144,18 +144,6 @@ function MentoringConsumables({ } }, [allMentorsAvailable]); - const checkForConsumableAvailable = (consumableList, serviceSelected) => { - const filteredConsumables = consumableList.filter((consumable) => consumable?.mentorship_services?.some((service) => serviceSelected?.slug === service.slug)); - - const validConsumable = filteredConsumables.find((consumable) => consumable?.balance?.unit === -1 || consumable?.balance?.unit > 0); - - if (validConsumable) { - return validConsumable; - } - const balanceZeroConsumable = filteredConsumables.find((consumable) => consumable?.balance?.unit === 0); - return balanceZeroConsumable; - }; - const manageMentorsData = (service, data) => { reportDatalayer({ dataLayer: { @@ -165,8 +153,7 @@ function MentoringConsumables({ mentorship_service: service?.slug, }, }); - const relatedConsumable = checkForConsumableAvailable(consumables, service); - + const relatedConsumable = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); setProgramMentors(data); setConsumableOfService({ ...relatedConsumable, @@ -555,7 +542,7 @@ MentoringConsumables.defaultProps = { consumables: {}, mentorshipService: {}, programServices: [], - setProgramMentors: () => {}, + setProgramMentors: () => { }, subscriptionData: {}, allSubscriptions: [], }; diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index 338a7a609..57607cc95 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -390,11 +390,6 @@ 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); - console.log('AAAAAAAAAA', availableConsumables); - console.log('CURRENT CONSUMABLE', currentConsumable); - console.log('suscription for current event', subscriptionsForCurrentEvent); - console.log('SUSCRIPCIONT', subscriptions); - useEffect(() => { if (subscriptionsForCurrentEvent.length === 0) setDenyAccessToEvent(true); else { From df18c21ee32731a5543065dda1b1af1ac7551b88 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Wed, 11 Sep 2024 18:43:15 -0400 Subject: [PATCH 06/12] :recycle: refactor of the code of mentoring --- .../components/SupportSidebar/Mentoring.jsx | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index c900a2e88..23028ea12 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -20,24 +20,35 @@ 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 { state } = useCohortHandler(); const { cohortSession } = state; const router = useRouter(); - const [consumables, setConsumables] = useState({}); + const { isLoading, user } = useAuth(); + const { slug } = router.query; + + const [savedChanges, setSavedChanges] = 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 step1 = !mentoryProps?.service; + const step2 = mentoryProps?.service && !mentoryProps?.date; - const [searchProps, setSearchProps] = useState({ - serviceSearch: '', - mentorSearch: '', - }); + const formatDate = (date, formatStr) => (date ? format(new Date(date), formatStr, { locale: es }) : null); + + const dateFormated = { + en: formatDate(mentoryProps?.date, 'MMMM dd'), + es: formatDate(mentoryProps?.date, "dd 'de' MMMM"), + }; + + const dateFormated2 = { + en: formatDate(mentoryProps?.date, 'MMMM dd, yyyy'), + es: formatDate(mentoryProps?.date, "dd 'de' MMMM, yyyy"), + }; const servicesFiltered = programServices.list.filter( (l) => l.name.toLowerCase().includes(searchProps.serviceSearch), @@ -62,22 +73,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(':'); @@ -91,9 +93,6 @@ function Mentoring({ } }, [mentoryProps?.time]); - const step1 = !mentoryProps?.service; - const step2 = mentoryProps?.service && !mentoryProps?.date; - const getAllMentorsAvailable = async () => { const servicesSlugs = programServices.list.map((service) => service?.slug); @@ -105,7 +104,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), @@ -140,6 +138,8 @@ function Mentoring({ if (balanceA > 0 && balanceB <= 0) return -1; if (balanceA <= 0 && balanceB > 0) return 1; + if (balanceA > 0 && balanceB > 0) return balanceB - balanceA; + return 0; }); @@ -169,19 +169,17 @@ function Mentoring({ const existsCohortSession = typeof cohortSession?.available_as_saas === 'boolean'; if (existsCohortSession) { setIsAvailableForConsumables(cohortSession?.available_as_saas); + return; } - if (!existsCohortSession) { - if (allCohorts.length > 0) { - setIsAvailableForConsumables(allCohorts?.some((c) => c.cohort?.available_as_saas === true)); + if (allCohorts.length > 0) { + const hasBootcampCohort = allCohorts?.some((c) => c.cohort?.available_as_saas === false); + if (hasBootcampCohort) { + setIsAvailableForConsumables(false); } } }, [allCohorts]); - const mentorshipService = consumables?.length > 0 ? consumables?.find( - (c) => subscriptions.some( - (s) => c?.slug.toLowerCase() === s?.selected_mentorship_service_set?.slug.toLowerCase(), - ), - ) : {}; + const mentorshipService = consumables.length > 0 ? consumables[0] : {}; return !isLoading && user?.id && ( From d8f4c46d6d57be4b0ad310783d5c2341dcbf4d7a Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Mon, 16 Sep 2024 16:33:42 -0400 Subject: [PATCH 07/12] :bug: fix bug related to consumables when user comes from /program/slug --- src/pages/choose-program/index.jsx | 2 ++ 1 file changed, 2 insertions(+) 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; From 157e64fdf6918941f8dbccdf8ad934fbf5926b5c Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Tue, 17 Sep 2024 19:11:04 -0400 Subject: [PATCH 08/12] :recycle: refactor of consumablesCode --- .../components/SupportSidebar/Mentoring.jsx | 104 ++--- .../SupportSidebar/MentoringConsumables.jsx | 355 +++++++++--------- 2 files changed, 197 insertions(+), 262 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index 23028ea12..663542953 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'; @@ -22,12 +19,11 @@ function Mentoring({ }) { // const toast = useToast(); const { t } = useTranslation('dashboard'); - const { state } = useCohortHandler(); - const { cohortSession } = state; const router = useRouter(); const { isLoading, user } = useAuth(); const { slug } = router.query; - + const { state } = useCohortHandler(); + const { cohortSession } = state; const [savedChanges, setSavedChanges] = useState({}); const [consumables, setConsumables] = useState([]); const [mentoryProps, setMentoryProps] = useState({}); @@ -36,23 +32,7 @@ function Mentoring({ const [isAvailableForConsumables, setIsAvailableForConsumables] = useState(true); const [searchProps, setSearchProps] = useState({ serviceSearch: '', mentorSearch: '' }); const step1 = !mentoryProps?.service; - const step2 = mentoryProps?.service && !mentoryProps?.date; - - const formatDate = (date, formatStr) => (date ? format(new Date(date), formatStr, { locale: es }) : null); - - const dateFormated = { - en: formatDate(mentoryProps?.date, 'MMMM dd'), - es: formatDate(mentoryProps?.date, "dd 'de' MMMM"), - }; - - const dateFormated2 = { - en: formatDate(mentoryProps?.date, 'MMMM dd, yyyy'), - es: formatDate(mentoryProps?.date, "dd 'de' MMMM, yyyy"), - }; - - const servicesFiltered = programServices.list.filter( - (l) => l.name.toLowerCase().includes(searchProps.serviceSearch), - ); + const step2 = mentoryProps?.service; const filterServices = () => { if (subscriptionData?.selected_mentorship_service_set?.mentorship_services?.length > 0) { @@ -169,70 +149,38 @@ function Mentoring({ const existsCohortSession = typeof cohortSession?.available_as_saas === 'boolean'; if (existsCohortSession) { setIsAvailableForConsumables(cohortSession?.available_as_saas); - return; - } - if (allCohorts.length > 0) { - const hasBootcampCohort = allCohorts?.some((c) => c.cohort?.available_as_saas === false); - if (hasBootcampCohort) { - setIsAvailableForConsumables(false); - } } }, [allCohorts]); - const mentorshipService = consumables.length > 0 ? consumables[0] : {}; + console.log(cohortSession); 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, + savedChanges, + setSavedChanges, + mentorsFiltered, + step1, + step2, + allMentorsAvailable, + subscriptionData, + isAvailableForConsumables, + allSubscriptions: subscriptions, + }} + /> ); } diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 46eea4c96..af5e50ef4 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 }) { @@ -90,10 +90,10 @@ function ProfilesSection({ } function MentoringConsumables({ - mentoryProps, width, consumables, mentorshipService, setMentoryProps, - programServices, dateFormated, servicesFiltered, searchProps, + mentoryProps, width, consumables, isAvailableForConsumables, setMentoryProps, + programServices, servicesFiltered, searchProps, setSearchProps, setProgramMentors, savedChanges, setSavedChanges, - mentorsFiltered, dateFormated2, allMentorsAvailable, subscriptionData, allSubscriptions, + mentorsFiltered, allMentorsAvailable, subscriptionData, allSubscriptions, }) { const { t } = useTranslation('dashboard'); @@ -108,29 +108,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 [shouldHandleService, setShouldHandleService] = useState(true); const router = useRouter(); const toast = useToast(); - const { slug } = router.query; + const { slug, queryService, queryMentor } = router.query; - const mentorshipBalance = mentorshipService?.balance?.unit || mentorshipService?.balance || consumableOfService?.balance?.unit; + 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 +147,7 @@ function MentoringConsumables({ } }, [allMentorsAvailable]); - const manageMentorsData = (service, data) => { + const manageMentorsData = (service, mentors) => { reportDatalayer({ dataLayer: { event: 'select_mentorship_service', @@ -153,15 +156,17 @@ function MentoringConsumables({ mentorship_service: service?.slug, }, }); + console.log('AAAAAAAAAAAA', service); const relatedConsumable = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); - setProgramMentors(data); + setProgramMentors(mentors); setConsumableOfService({ ...relatedConsumable, balance: { - unit: service?.academy?.available_as_saas === false ? -1 : relatedConsumable?.balance?.unit, + unit: (service?.academy?.available_as_saas === false || isAvailableForConsumables === false) ? -1 : relatedConsumable?.balance?.unit, }, available_as_saas: service?.academy?.available_as_saas, }); + setTimeout(() => { setMentoryProps({ ...mentoryProps, service }); setSavedChanges({ ...savedChanges, service }); @@ -172,6 +177,7 @@ function MentoringConsumables({ try { if (allMentorsAvailable.length > 0) { const mentorsByService = allMentorsAvailable.filter((mentor) => mentor.services.some((s) => s.slug === service.slug)); + console.log(service); manageMentorsData(service, mentorsByService); } else { const res = await bc.mentorship({ @@ -194,7 +200,51 @@ 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))); + + let servWithMentorsAvailable; + + if (queryMentor && allMentorsAvailable.length > 0) { + const mentorFound = allMentorsAvailable.find((ment) => ment.slug === queryMentor); + if (mentorFound && !hasReset) { + servWithMentorsAvailable = servicesFiltered.filter((service) => mentorFound.services.some((mentServ) => mentServ.slug === service.slug)); + } else { + servWithMentorsAvailable = getAllServicesWithMentors(); + } + } else { + servWithMentorsAvailable = getAllServicesWithMentors(); + } + + 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) { + handleService(serviceFound); + } else { + toast({ + position: 'top', + title: 'Error', + description: `${queryService} Service nor found`, + status: 'error', + duration: 7000, + isClosable: true, + }); + } + setOpen(true); + setShouldHandleService(false); + } + }, [hasReset, servicesWithMentorsAvailable]); + + const reset = () => { + if (mentoryProps?.service) setMentoryProps({}); + else setOpen(false); + setHasReset(true); + }; const handleGetMoreMentorships = () => { setIsFetchingDataForModal(true); @@ -212,6 +262,7 @@ function MentoringConsumables({ }) .finally(() => setIsFetchingDataForModal(false)); }; + const reportBookMentor = () => { reportDatalayer({ dataLayer: { @@ -236,12 +287,12 @@ function MentoringConsumables({ > {open && mentoryProps?.service && ( - setMentoryProps({})} cursor="pointer"> + reset()} cursor="pointer"> )} {open && !mentoryProps?.service && ( - setOpen(false)} cursor="pointer"> + reset()} cursor="pointer"> )} @@ -285,11 +336,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 + + {/* onClick={() => { setMentoryProps({ ...mentoryProps, mentor }); setSavedChanges({ ...savedChanges, mentor }); }} */} + {`${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')} - - )} + )} + )} @@ -520,10 +511,8 @@ MentoringConsumables.propTypes = { mentoryProps: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])), width: 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, @@ -531,7 +520,6 @@ MentoringConsumables.propTypes = { 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])), }; @@ -540,7 +528,6 @@ MentoringConsumables.defaultProps = { mentoryProps: [], width: '100%', consumables: {}, - mentorshipService: {}, programServices: [], setProgramMentors: () => { }, subscriptionData: {}, From 297ec6648a5f31844171aa37351ce49822b390a0 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Tue, 17 Sep 2024 19:12:47 -0400 Subject: [PATCH 09/12] :recycle: refactor of consumablesCode --- src/common/components/SupportSidebar/Mentoring.jsx | 2 -- src/common/components/SupportSidebar/MentoringConsumables.jsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index 663542953..1aa773423 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -152,8 +152,6 @@ function Mentoring({ } }, [allCohorts]); - console.log(cohortSession); - return !isLoading && user?.id && ( diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index af5e50ef4..f53716ded 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -156,7 +156,6 @@ function MentoringConsumables({ mentorship_service: service?.slug, }, }); - console.log('AAAAAAAAAAAA', service); const relatedConsumable = consumables.find((consumable) => consumable?.mentorship_services?.some((c) => c?.slug === service?.slug)); setProgramMentors(mentors); setConsumableOfService({ @@ -177,7 +176,6 @@ function MentoringConsumables({ try { if (allMentorsAvailable.length > 0) { const mentorsByService = allMentorsAvailable.filter((mentor) => mentor.services.some((s) => s.slug === service.slug)); - console.log(service); manageMentorsData(service, mentorsByService); } else { const res = await bc.mentorship({ From d4694619e8e317992243f409cd79cbbd0f7b2722 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Wed, 18 Sep 2024 14:17:11 -0400 Subject: [PATCH 10/12] :recycle: refactor of the code --- .../components/SupportSidebar/Mentoring.jsx | 22 +------ .../SupportSidebar/MentoringConsumables.jsx | 58 ++++++++----------- 2 files changed, 26 insertions(+), 54 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index 1aa773423..c58c328ec 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -24,15 +24,12 @@ function Mentoring({ const { slug } = router.query; const { state } = useCohortHandler(); const { cohortSession } = state; - const [savedChanges, setSavedChanges] = useState({}); const [consumables, setConsumables] = useState([]); const [mentoryProps, setMentoryProps] = useState({}); const [allMentorsAvailable, setAllMentorsAvailable] = useState([]); const [programMentors, setProgramMentors] = useState([]); const [isAvailableForConsumables, setIsAvailableForConsumables] = useState(true); const [searchProps, setSearchProps] = useState({ serviceSearch: '', mentorSearch: '' }); - const step1 = !mentoryProps?.service; - const step2 = mentoryProps?.service; const filterServices = () => { if (subscriptionData?.selected_mentorship_service_set?.mentorship_services?.length > 0) { @@ -60,19 +57,6 @@ function Mentoring({ }, ); - 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 getAllMentorsAvailable = async () => { const servicesSlugs = programServices.list.map((service) => service?.slug); @@ -84,7 +68,7 @@ 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, @@ -168,11 +152,7 @@ function Mentoring({ searchProps, setSearchProps, setProgramMentors, - savedChanges, - setSavedChanges, mentorsFiltered, - step1, - step2, allMentorsAvailable, subscriptionData, isAvailableForConsumables, diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index f53716ded..c4e427a35 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -91,12 +91,11 @@ function ProfilesSection({ function MentoringConsumables({ mentoryProps, width, consumables, isAvailableForConsumables, setMentoryProps, - programServices, servicesFiltered, searchProps, - setSearchProps, setProgramMentors, savedChanges, setSavedChanges, + 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)'); @@ -112,9 +111,8 @@ function MentoringConsumables({ const [hasReset, setHasReset] = useState(false); const [shouldHandleService, setShouldHandleService] = useState(true); const router = useRouter(); + const { slug } = router.query; const toast = useToast(); - const { slug, queryService, queryMentor } = router.query; - const mentorshipBalance = consumableOfService?.balance?.unit; const currentBalance = Number(mentorshipBalance && mentorshipBalance); @@ -168,7 +166,6 @@ function MentoringConsumables({ setTimeout(() => { setMentoryProps({ ...mentoryProps, service }); - setSavedChanges({ ...savedChanges, service }); }, 50); }; @@ -209,6 +206,16 @@ function MentoringConsumables({ servWithMentorsAvailable = servicesFiltered.filter((service) => mentorFound.services.some((mentServ) => mentServ.slug === service.slug)); } else { servWithMentorsAvailable = getAllServicesWithMentors(); + if (!hasReset) { + toast({ + position: 'top', + title: 'Error', + description: `${queryMentor} mentor not found`, + status: 'error', + duration: 7000, + isClosable: true, + }); + } } } else { servWithMentorsAvailable = getAllServicesWithMentors(); @@ -227,7 +234,7 @@ function MentoringConsumables({ toast({ position: 'top', title: 'Error', - description: `${queryService} Service nor found`, + description: `${queryService} service not found ${queryMentor ? `for ${queryMentor}` : ''}`, status: 'error', duration: 7000, isClosable: true, @@ -261,16 +268,16 @@ 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, }, }); }; @@ -298,7 +305,7 @@ function MentoringConsumables({ {!mentoryProps?.service && (consumables?.mentorship_service_sets?.length !== 0 || currentBalance !== 0) && ( <> - + {t('supportSideBar.mentoring')}
@@ -389,24 +396,6 @@ function MentoringConsumables({
)} - {mentoryProps?.mentor && ( - - {`selected - - - {`${mentoryProps.mentor.user.first_name} ${mentoryProps.mentor.user.last_name}`} - - - - )} {!mentoryProps?.service && programServices.length > 0 && ( <> @@ -445,7 +434,6 @@ function MentoringConsumables({ )} - {/* onClick={() => { setMentoryProps({ ...mentoryProps, mentor }); setSavedChanges({ ...savedChanges, mentor }); }} */} {`${mentor?.user?.first_name} { }, From 437e4081b31b132ba1f0e63c9d10c6c42138ce84 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Wed, 18 Sep 2024 14:27:02 -0400 Subject: [PATCH 11/12] :recycle: refactor of the code --- public/locales/en/dashboard.json | 3 +++ public/locales/es/dashboard.json | 3 +++ .../components/SupportSidebar/MentoringConsumables.jsx | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/public/locales/en/dashboard.json b/public/locales/en/dashboard.json index 2eba43f76..f5ea97528 100644 --- a/public/locales/en/dashboard.json +++ b/public/locales/en/dashboard.json @@ -84,6 +84,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/es/dashboard.json b/public/locales/es/dashboard.json index 0a4b24808..400675639 100644 --- a/public/locales/es/dashboard.json +++ b/public/locales/es/dashboard.json @@ -84,6 +84,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/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index c4e427a35..602305132 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -202,6 +202,7 @@ function MentoringConsumables({ if (queryMentor && allMentorsAvailable.length > 0) { const mentorFound = allMentorsAvailable.find((ment) => ment.slug === queryMentor); + if (mentorFound && !hasReset) { servWithMentorsAvailable = servicesFiltered.filter((service) => mentorFound.services.some((mentServ) => mentServ.slug === service.slug)); } else { @@ -210,7 +211,7 @@ function MentoringConsumables({ toast({ position: 'top', title: 'Error', - description: `${queryMentor} mentor not found`, + description: `${t('supportSideBar.mentor-not-found')} "${queryMentor}"`, status: 'error', duration: 7000, isClosable: true, @@ -228,18 +229,20 @@ function MentoringConsumables({ useEffect(() => { if (queryService && servicesWithMentorsAvailable?.length > 0 && shouldHandleService && !hasReset) { const serviceFound = servicesWithMentorsAvailable.find((service) => service.slug === queryService); + if (serviceFound) { handleService(serviceFound); } else { toast({ position: 'top', title: 'Error', - description: `${queryService} service not found ${queryMentor ? `for ${queryMentor}` : ''}`, + description: `${t('supportSideBar.service-not-found')} "${queryService}" ${queryMentor ? `${t('supportSideBar.for')} "${queryMentor}"` : ''}`, status: 'error', duration: 7000, isClosable: true, }); } + setOpen(true); setShouldHandleService(false); } From 75f72b061e36775c362fa0ea3f5b45f7e98f9af3 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Thu, 19 Sep 2024 18:29:41 -0400 Subject: [PATCH 12/12] :recycle: refactor --- .../components/SupportSidebar/Mentoring.jsx | 6 +- .../SupportSidebar/MentoringConsumables.jsx | 57 ++++++++++--------- src/pages/workshops/[event_slug].jsx | 4 +- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/common/components/SupportSidebar/Mentoring.jsx b/src/common/components/SupportSidebar/Mentoring.jsx index c58c328ec..57fc097c0 100644 --- a/src/common/components/SupportSidebar/Mentoring.jsx +++ b/src/common/components/SupportSidebar/Mentoring.jsx @@ -28,7 +28,7 @@ function Mentoring({ const [mentoryProps, setMentoryProps] = useState({}); const [allMentorsAvailable, setAllMentorsAvailable] = useState([]); const [programMentors, setProgramMentors] = useState([]); - const [isAvailableForConsumables, setIsAvailableForConsumables] = useState(true); + const [cohortSessionIsSaaS, setCohortSessionIsSaaS] = useState(true); const [searchProps, setSearchProps] = useState({ serviceSearch: '', mentorSearch: '' }); const filterServices = () => { @@ -132,7 +132,7 @@ function Mentoring({ useEffect(() => { const existsCohortSession = typeof cohortSession?.available_as_saas === 'boolean'; if (existsCohortSession) { - setIsAvailableForConsumables(cohortSession?.available_as_saas); + setCohortSessionIsSaaS(cohortSession?.available_as_saas); } }, [allCohorts]); @@ -155,7 +155,7 @@ function Mentoring({ mentorsFiltered, allMentorsAvailable, subscriptionData, - isAvailableForConsumables, + cohortSessionIsSaaS, allSubscriptions: subscriptions, }} /> diff --git a/src/common/components/SupportSidebar/MentoringConsumables.jsx b/src/common/components/SupportSidebar/MentoringConsumables.jsx index 602305132..fddb8b96e 100644 --- a/src/common/components/SupportSidebar/MentoringConsumables.jsx +++ b/src/common/components/SupportSidebar/MentoringConsumables.jsx @@ -90,7 +90,7 @@ function ProfilesSection({ } function MentoringConsumables({ - mentoryProps, width, consumables, isAvailableForConsumables, setMentoryProps, + mentoryProps, width, consumables, cohortSessionIsSaaS, setMentoryProps, programServices, servicesFiltered, searchProps, setSearchProps, setProgramMentors, mentorsFiltered, allMentorsAvailable, subscriptionData, allSubscriptions, queryService, queryMentor, titleSize, @@ -109,6 +109,7 @@ function MentoringConsumables({ 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 { slug } = router.query; @@ -159,7 +160,7 @@ function MentoringConsumables({ setConsumableOfService({ ...relatedConsumable, balance: { - unit: (service?.academy?.available_as_saas === false || isAvailableForConsumables === false) ? -1 : relatedConsumable?.balance?.unit, + unit: (service?.academy?.available_as_saas === false || cohortSessionIsSaaS === false) ? -1 : relatedConsumable?.balance?.unit, }, available_as_saas: service?.academy?.available_as_saas, }); @@ -197,42 +198,43 @@ function MentoringConsumables({ 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)); - let servWithMentorsAvailable; + const showErrorToast = () => { + toast({ + position: 'top', + title: 'Error', + description: `${t('supportSideBar.mentor-not-found')} "${queryMentor}"`, + status: 'error', + duration: 7000, + isClosable: true, + }); + }; - if (queryMentor && allMentorsAvailable.length > 0) { + let servWithMentorsAvailable = getAllServicesWithMentors(); + + if (queryMentor && allMentorsAvailable.length > 0 && !hasReset) { const mentorFound = allMentorsAvailable.find((ment) => ment.slug === queryMentor); - if (mentorFound && !hasReset) { - servWithMentorsAvailable = servicesFiltered.filter((service) => mentorFound.services.some((mentServ) => mentServ.slug === service.slug)); - } else { - servWithMentorsAvailable = getAllServicesWithMentors(); - if (!hasReset) { - toast({ - position: 'top', - title: 'Error', - description: `${t('supportSideBar.mentor-not-found')} "${queryMentor}"`, - status: 'error', - duration: 7000, - isClosable: true, - }); - } + if (!mentorFound && notifyError) { + showErrorToast(); + setNotifyError(false); } - } else { - servWithMentorsAvailable = getAllServicesWithMentors(); + if (mentorFound) servWithMentorsAvailable = getServicesWithMentor(mentorFound); } setServicesWithMentorsAvailable(servWithMentorsAvailable); - if (!hasReset && queryMentor) setOpen(true); + + 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) { - handleService(serviceFound); - } else { + if (!serviceFound && notifyError) { toast({ position: 'top', title: 'Error', @@ -241,8 +243,11 @@ function MentoringConsumables({ duration: 7000, isClosable: true, }); + setNotifyError(false); + return; } + handleService(serviceFound); setOpen(true); setShouldHandleService(false); } @@ -295,12 +300,12 @@ function MentoringConsumables({ > {open && mentoryProps?.service && ( - reset()} cursor="pointer"> + )} {open && !mentoryProps?.service && ( - reset()} cursor="pointer"> + )} diff --git a/src/pages/workshops/[event_slug].jsx b/src/pages/workshops/[event_slug].jsx index 57607cc95..e910cf61f 100644 --- a/src/pages/workshops/[event_slug].jsx +++ b/src/pages/workshops/[event_slug].jsx @@ -392,9 +392,7 @@ function Page({ eventData, asset }) { useEffect(() => { if (subscriptionsForCurrentEvent.length === 0) setDenyAccessToEvent(true); - else { - setDenyAccessToEvent(false); - } + else setDenyAccessToEvent(false); }, [subscriptionsForCurrentEvent]); const dynamicFormInfo = () => {