diff --git a/src/app/pages/global-reach/global-reach.js b/src/app/pages/global-reach/global-reach.js deleted file mode 100644 index 3ac5a72e4..000000000 --- a/src/app/pages/global-reach/global-reach.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import LoaderPage from '~/components/jsx-helpers/loader-page'; -import {camelCaseKeys} from '~/helpers/page-data-utils'; -import Map from './map/map'; -import Statistics from './statistics/stat'; -import StudentInfo from './studentinfo/studentinfo'; -import SchoolMap from './schoolmap/schoolmap'; - -function preprocessData(data) { - return camelCaseKeys( - Reflect.ownKeys(data).reduce((result, key) => { - const value = data[key]; - const matches = key.match(/(section_.)_(.*)/); - - if (matches) { - const [_, sectionKey, newKey] = matches; - - if (!(sectionKey in result)) { - result[sectionKey] = {}; - } - result[sectionKey][newKey] = value; - } else { - result[key] = value; - } - return result; - }, {}) - ); -} - -function GlobalReachPage({data}) { - const ppData = preprocessData(data); - - return ( - - - - - - - ); -} - -const slug = 'pages/global-reach'; - -export default function GlobalReachLoader() { - return ( -
- -
- ); -} diff --git a/src/app/pages/global-reach/global-reach.tsx b/src/app/pages/global-reach/global-reach.tsx new file mode 100644 index 000000000..29aa16bfc --- /dev/null +++ b/src/app/pages/global-reach/global-reach.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import LoaderPage from '~/components/jsx-helpers/loader-page'; +import {camelCaseKeys, Json} from '~/helpers/page-data-utils'; +import Map from './map/map'; +import Statistics, {CardData} from './statistics/stat'; +import StudentInfo, {StudentData} from './studentinfo/studentinfo'; +import SchoolMap from './schoolmap/schoolmap'; + +type RawData = Record; +type ProcessedData = { + title: string; + headerText: string; + mapImageUrl: string; + section1: {cards: CardData[]}; + section2: StudentData; + section3: Parameters[0]; +}; + +function preprocessData(data: RawData) { + return camelCaseKeys( + Object.keys(data).reduce( + (result, key) => { + const value = data[key]; + const matches = key.match(/(section_.)_(.*)/); + + if (matches) { + const [_, sectionKey, newKey] = matches; + + if (!(sectionKey in result)) { + result[sectionKey] = {}; + } + (result[sectionKey] as Record)[newKey] = + value; + } else { + result[key] = value; + } + return result; + }, + {} as Record + ) + ) as ProcessedData; +} + +function GlobalReachPage({data}: {data: RawData}) { + const ppData = preprocessData(data); + + return ( + + + + + + + ); +} + +const slug = 'pages/global-reach'; + +export default function GlobalReachLoader() { + return ( +
+ +
+ ); +} diff --git a/src/app/pages/global-reach/map/map.js b/src/app/pages/global-reach/map/map.tsx similarity index 59% rename from src/app/pages/global-reach/map/map.js rename to src/app/pages/global-reach/map/map.tsx index 33209989f..e52326c7e 100644 --- a/src/app/pages/global-reach/map/map.js +++ b/src/app/pages/global-reach/map/map.tsx @@ -1,10 +1,21 @@ import React from 'react'; import './map.scss'; -export default function Map({title, buttonText, imageUrl}) { +export default function Map({ + title, + buttonText, + imageUrl +}: { + title: string; + buttonText: string; + imageUrl: string; +}) { return (
-
+

{title}

diff --git a/src/app/pages/global-reach/schoolmap/schoolmap.js b/src/app/pages/global-reach/schoolmap/schoolmap.tsx similarity index 68% rename from src/app/pages/global-reach/schoolmap/schoolmap.js rename to src/app/pages/global-reach/schoolmap/schoolmap.tsx index 87c50ddcc..dc2b96d50 100644 --- a/src/app/pages/global-reach/schoolmap/schoolmap.js +++ b/src/app/pages/global-reach/schoolmap/schoolmap.tsx @@ -3,7 +3,17 @@ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight'; import './schoolmap.scss'; -export default function SchoolMap({heading, blurb, link: linkUrl, cta: linkText}) { +export default function SchoolMap({ + heading, + blurb, + link: linkUrl, + cta: linkText +}: { + heading: string; + blurb: string; + link: string; + cta: string; +}) { return (
@@ -17,7 +27,12 @@ export default function SchoolMap({heading, blurb, link: linkUrl, cta: linkText}
-
+
+ +
); diff --git a/src/app/pages/global-reach/statistics/stat.js b/src/app/pages/global-reach/statistics/stat.tsx similarity index 52% rename from src/app/pages/global-reach/statistics/stat.js rename to src/app/pages/global-reach/statistics/stat.tsx index 559f922e7..8eb7b0de6 100644 --- a/src/app/pages/global-reach/statistics/stat.js +++ b/src/app/pages/global-reach/statistics/stat.tsx @@ -1,11 +1,25 @@ import React from 'react'; import './stat.scss'; -function Card({item}) { +export type CardData = { + image: { + image: string; + altText: string; + }; + number: string; + unit: string; + description: string; +}; + +function Card({item}: {item: CardData}) { return (
- {item.image.altText} + {item.image.altText}
@@ -18,11 +32,13 @@ function Card({item}) { ); } -export default function Statistics({cards}) { +export default function Statistics({cards}: {cards: CardData[]}) { return (
- {cards.map((card) => )} + {cards.map((card) => ( + + ))}
); diff --git a/src/app/pages/global-reach/studentinfo/studentinfo.js b/src/app/pages/global-reach/studentinfo/studentinfo.tsx similarity index 56% rename from src/app/pages/global-reach/studentinfo/studentinfo.js rename to src/app/pages/global-reach/studentinfo/studentinfo.tsx index f040500ce..ef8c581bf 100644 --- a/src/app/pages/global-reach/studentinfo/studentinfo.js +++ b/src/app/pages/global-reach/studentinfo/studentinfo.tsx @@ -1,17 +1,40 @@ import React from 'react'; import './studentinfo.scss'; +export type StudentData = { + header1: string; + blurb1: string; + cta1: string; + link1: string; + image1Url: string; + header2: string; + blurb2: string; + cta2: string; + link2: string; + image2Url: string; +}; + export default function StudentInfo({ - header1, blurb1, cta1, link1, image1Url, - header2, blurb2, cta2, link2, image2Url -}) { + header1, + blurb1, + cta1, + link1, + image1Url, + header2, + blurb2, + cta2, + link2, + image2Url +}: StudentData) { return (
{header1}

{blurb1}

- {cta1} + + {cta1} +
Student
@@ -21,7 +44,9 @@ export default function StudentInfo({
{header2}

{blurb2}

- {cta2} + + {cta2} +
diff --git a/test/helpers/fetch-mocker.js b/test/helpers/fetch-mocker.js index 168ac92d0..e9601677d 100644 --- a/test/helpers/fetch-mocker.js +++ b/test/helpers/fetch-mocker.js @@ -21,6 +21,7 @@ import faq from '../src/data/faq'; import flags from '../src/data/flags'; import footerData from '../src/data/footer'; import formHeadings from '../src/data/form-headings'; +import globalReachData from '../src/data/global-reach'; import impact from '../src/data/impact'; import institutionalPartnershipData from '../src/data/institutional-partnership'; import kineticData from '../src/data/kinetic'; @@ -74,6 +75,7 @@ global.fetch = jest.fn().mockImplementation((...args) => { const isFooter = (/api\/footer/).test(args[0]); const isFormHeading = (/form-headings/).test(args[0]); const isGiveBanner = args[0].endsWith('snippets/givebanner/'); + const isGlobalReach = args[0].includes('/global-reach/'); const isImpact = args[0].includes('/pages/impact'); const isInstitutionalPartnership = (/pages\/institutional-partners/).test(args[0]); const isKinetic = args[0].endsWith('kinetic/'); @@ -144,6 +146,8 @@ global.fetch = jest.fn().mockImplementation((...args) => { payload = formHeadings; } else if (isGiveBanner) { payload = {}; + } else if (isGlobalReach) { + payload = globalReachData; } else if (isHomepage) { payload = openstaxHomepageData; } else if (isImpact) { diff --git a/test/src/data/global-reach.js b/test/src/data/global-reach.js new file mode 100644 index 000000000..c7eb638f1 --- /dev/null +++ b/test/src/data/global-reach.js @@ -0,0 +1,115 @@ +export default { + id: 306, + meta: { + slug: 'global-reach', + seo_title: '', + search_description: '', + type: 'pages.MapPage', + detail_url: 'https://openstax.org/apps/cms/api/v2/pages/306/', + html_url: 'https://openstax.org/global-reach/', + show_in_menus: false, + first_published_at: '2019-02-22T14:05:25.269000-06:00', + alias_of: null, + parent: { + id: 821, + meta: { + type: 'pages.RootPage', + detail_url: 'https://openstax.org/apps/cms/api/v2/pages/821/', + html_url: 'https://openstax.org/' + }, + title: 'Home' + }, + locale: 'en' + }, + title: "We're changing the world, one book at a time!", + header_text: 'Check out our interactive map', + section_1_cards: [ + { + type: 'card', + value: { + image: { + image: 661, + alt_text: '', + link: '', + alignment: 'left', + identifier: '' + }, + number: '9', + unit: 'million', + description: 'students have used OpenStax textbooks' + }, + id: 'bf261a46-e88f-408f-9521-5540764b0b94' + }, + { + type: 'card', + value: { + image: { + image: 662, + alt_text: '', + link: '', + alignment: 'left', + identifier: '' + }, + number: '56', + unit: '%', + description: + 'of degree-granting institutions in the US use OpenStax' + }, + id: 'e9759079-5b69-4b17-ab50-fd9faddfed46' + }, + { + type: 'card', + value: { + image: { + image: 663, + alt_text: '', + link: '', + alignment: 'left', + identifier: '' + }, + number: '$835', + unit: 'million', + description: 'saved by students since 2012' + }, + id: 'f01a5792-91f2-431b-92fb-9d780b4c43e3' + }, + { + type: 'card', + value: { + image: { + image: 664, + alt_text: '', + link: '', + alignment: 'left', + identifier: '' + }, + number: '7,000', + unit: '+', + description: 'schools use OpenStax' + }, + id: '56540272-83d5-4273-b389-67fabc766f95' + } + ], + map_image_url: + 'https://assets.openstax.org/oscms-prodcms/media/original_images/global-map.original.original.jpg', + section_2_header_1: 'Ready to join the OpenStax movement?', + section_2_blurb_1: + "We’re proud of how far we’ve come, but we need YOU to continue our mission of increasing student access to education. Let us know you're using OpenStax and put your school on the map!", + section_2_cta_1: "I'm using OpenStax", + section_2_link_1: 'https://openstax.org/adoption', + section_2_image_1_url: + 'https://assets.openstax.org/oscms-prodcms/media/original_images/girl.png', + section_2_header_2: 'Want to help?', + section_2_blurb_2: + 'OpenStax is part of Rice University which is a 501(c)(3) nonprofit charitable corporation, which means that we rely on our supporters to grow and expand our library. With your help, we can bring open education resources to even more students across the world.', + section_2_cta_2: 'I want to give', + section_2_link_2: 'https://riceconnect.rice.edu/donation/support-openstax', + section_2_image_2_url: + 'https://assets.openstax.org/oscms-prodcms/media/original_images/girl_and_guy.png', + section_3_heading: 'Put your school on the Map', + section_3_blurb: + 'Our prestigious Institutional Partner Program provides guidance for increasing the use of open educational resources on your campus.', + section_3_cta: 'I want to learn more', + section_3_link: 'https://openstax.org/institutional-partnership', + promote_image: null +}; diff --git a/test/src/pages/global-reach.test.tsx b/test/src/pages/global-reach.test.tsx new file mode 100644 index 000000000..a5e4eb855 --- /dev/null +++ b/test/src/pages/global-reach.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import {render, screen} from '@testing-library/preact'; +import MemoryRouter from '~/../../test/helpers/future-memory-router'; +import GlobalReachLoader from '~/pages/global-reach/global-reach'; + +describe('global-reach page', () => { + it('renders', async () => { + render( + + + + ); + await screen.findByRole('heading', {level: 1}); + }); +});