fix: add location resitriction for popular and trending courses (#1010)
Description: Filter courses on the basis of location VAN-1573
This commit is contained in:
20
src/recommendations/ProductCard/hooks/useProducts.jsx
Normal file
20
src/recommendations/ProductCard/hooks/useProducts.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import { filterLocationRestriction } from '../../data/utils';
|
||||
|
||||
export default function useProducts(countryCode) {
|
||||
const [popularProducts, setPopularProducts] = useState([]);
|
||||
const [trendingProducts, setTrendingProducts] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const popular = filterLocationRestriction(JSON.parse(getConfig().POPULAR_PRODUCTS), countryCode);
|
||||
const trending = filterLocationRestriction(JSON.parse(getConfig().TRENDING_PRODUCTS), countryCode);
|
||||
|
||||
setPopularProducts(popular);
|
||||
setTrendingProducts(trending);
|
||||
}, [countryCode]);
|
||||
|
||||
return { popularProducts, trendingProducts };
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
@@ -10,22 +11,21 @@ import { Helmet } from 'react-helmet';
|
||||
|
||||
import { POPULAR, TRENDING } from './data/constants';
|
||||
import messages from './messages';
|
||||
import useProducts from './ProductCard/hooks/useProducts';
|
||||
import RecommendationsList from './RecommendationsList';
|
||||
import { trackRecommendationsViewed } from './track';
|
||||
import { DEFAULT_REDIRECT_URL } from '../data/constants';
|
||||
|
||||
const RecommendationsPage = ({ location }) => {
|
||||
const RecommendationsPage = ({ location, countryCode }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const registrationResponse = location.state?.registrationResult;
|
||||
const userId = location.state?.userId;
|
||||
|
||||
const { popularProducts, trendingProducts } = useProducts(countryCode);
|
||||
const DASHBOARD_URL = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL);
|
||||
const POPULAR_PRODUCTS = JSON.parse(getConfig().POPULAR_PRODUCTS);
|
||||
const TRENDING_PRODUCTS = JSON.parse(getConfig().TRENDING_PRODUCTS);
|
||||
|
||||
useEffect(() => {
|
||||
trackRecommendationsViewed(POPULAR_PRODUCTS, POPULAR, false, userId);
|
||||
trackRecommendationsViewed(popularProducts, POPULAR, false, userId);
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const handleRedirection = () => {
|
||||
@@ -47,12 +47,12 @@ const RecommendationsPage = ({ location }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!POPULAR_PRODUCTS.length || !TRENDING_PRODUCTS.length) {
|
||||
if (!popularProducts.length || !trendingProducts.length) {
|
||||
handleRedirection();
|
||||
}
|
||||
|
||||
const handleOnSelect = (tabKey) => {
|
||||
const recommendations = tabKey === POPULAR ? POPULAR_PRODUCTS : TRENDING_PRODUCTS;
|
||||
const recommendations = tabKey === POPULAR ? popularProducts : trendingProducts;
|
||||
trackRecommendationsViewed(recommendations, tabKey, false, userId);
|
||||
};
|
||||
|
||||
@@ -83,13 +83,13 @@ const RecommendationsPage = ({ location }) => {
|
||||
>
|
||||
<Tab tabClassName="mb-3" eventKey={POPULAR} title={formatMessage(messages['recommendation.option.popular'])}>
|
||||
<RecommendationsList
|
||||
recommendations={POPULAR_PRODUCTS}
|
||||
recommendations={popularProducts}
|
||||
userId={userId}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab tabClassName="mb-3" eventKey={TRENDING} title={formatMessage(messages['recommendation.option.trending'])}>
|
||||
<RecommendationsList
|
||||
recommendations={TRENDING_PRODUCTS}
|
||||
recommendations={trendingProducts}
|
||||
userId={userId}
|
||||
/>
|
||||
</Tab>
|
||||
@@ -121,11 +121,18 @@ RecommendationsPage.propTypes = {
|
||||
userId: PropTypes.number,
|
||||
}),
|
||||
}),
|
||||
|
||||
countryCode: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
RecommendationsPage.defaultProps = {
|
||||
location: { state: {} },
|
||||
};
|
||||
|
||||
export default RecommendationsPage;
|
||||
const mapStateToProps = state => ({
|
||||
countryCode: state.register.backendCountryCode,
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
null,
|
||||
)(RecommendationsPage);
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { convertCourseRunKeytoCourseKey, useProductType } from '../utils';
|
||||
import mockedProductData from '../../tests/mockedData';
|
||||
import { convertCourseRunKeytoCourseKey, filterLocationRestriction, useProductType } from '../utils';
|
||||
|
||||
describe('UtilsTests', () => {
|
||||
it('should return the courseKey after parsing the activeCourseRun key', async () => {
|
||||
const courseKey = convertCourseRunKeytoCourseKey('course-v1:Demox+Test101+2023');
|
||||
expect(courseKey).toEqual('Demox+Test101');
|
||||
});
|
||||
it('should filter courses on the basis of country code', async () => {
|
||||
const products = filterLocationRestriction(mockedProductData, 'PK');
|
||||
expect(products.length).toEqual(1);
|
||||
});
|
||||
it('should return courseType and programType', async () => {
|
||||
const programType = useProductType(undefined, 'Professional Certificate');
|
||||
expect(programType).toEqual('Professional Certificate');
|
||||
|
||||
@@ -49,4 +49,17 @@ export const createCodeFriendlyProduct = (type) => type?.replace(/\s+/g, '-').re
|
||||
|
||||
export const truncateText = (input) => (input?.length > 50 ? `${input.substring(0, 50)}...` : input);
|
||||
|
||||
export const filterLocationRestriction = (products, countryCode) => products.filter((product) => {
|
||||
if (product.locationRestriction) {
|
||||
if (product.locationRestriction.restrictionType === 'allowlist') {
|
||||
return product.locationRestriction.countries.includes(countryCode);
|
||||
}
|
||||
if (product.locationRestriction.restrictionType === 'blocklist') {
|
||||
return !product.locationRestriction.countries.includes(countryCode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
export default convertCourseRunKeytoCourseKey;
|
||||
|
||||
@@ -44,7 +44,11 @@ describe('RecommendationsPageTests', () => {
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
store = mockStore({});
|
||||
store = mockStore({
|
||||
register: {
|
||||
backendCountryCode: 'PK',
|
||||
},
|
||||
});
|
||||
defaultProps = {
|
||||
location: {
|
||||
state: {
|
||||
|
||||
@@ -71,9 +71,9 @@ const mockedProductData = [
|
||||
status: 'active',
|
||||
hidden: false,
|
||||
degree: null,
|
||||
locationRestriction: null,
|
||||
cardType: 'program',
|
||||
cardIndex: 1,
|
||||
locationRestriction: { restrictionType: 'blocklist', countries: ['PK'] },
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user