Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved mobile and tablet exp #394

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions frontend/src/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@ interface PhilanthropicSupportersLinkProps {
const FunderTitle = () => (
<Title
order={2}
w={700}
style={{
fontFamily: 'Helvetica Neue',
fontSize: '32px',
lineHeight: '1.75rem',
textAlign: 'left',
}}
>
Support from scientific agencies
</Title>
Expand Down Expand Up @@ -131,11 +124,11 @@ const Funders = () => {
<Box style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<NSFLogo />
</Box>
{!isMobile && <Divider orientation="vertical" />}
<Divider orientation={isMobile? 'horizontal' : 'vertical'} />
<Box style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<IESSection />
</Box>
{!isMobile && <Divider orientation="vertical" />}
<Divider orientation={isMobile? 'horizontal' : 'vertical'} />
<Box style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<PhilanthropicSupportersLink isMobile={isMobile} />
</Box>
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/screens/achievements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Text, Button, Container, Title, Tabs, RingProgress, Image, Group,
import { useDisclosure } from '@mantine/hooks';
import { useApi } from '@lib';
import { launchStudy } from '@models';
import { TopNavBar, Footer } from '@components';
import { TopNavBar, Footer, LoadingAnimation } from '@components';
import { colors } from '@theme';
import { useFetchLearningPaths } from './learner/studies';
import { ParticipantStudy } from '@api';
Expand Down Expand Up @@ -179,7 +179,7 @@ const Achievements:FC = () => {
return (
<Box>
<TopNavBar />
<Container size="lg" my="xl">
{ Object.keys(learningPaths).length > 0 ? <><Container size="lg" my="xl">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can prob be cleaned up up above ie something like...

if (!Object.keys(learningPaths).length) {
  return <LoadingAnimation />
}

<Title mb="lg" mt="lg" order={2}>
Achievements
</Title>
Expand All @@ -196,7 +196,7 @@ const Achievements:FC = () => {
<Tabs.Panel value="Badges">
<Stack c={colors.text} >
<Text>Explore the study paths, track your progress, and access your digital badges.</Text>
<Group gap="xs" justify='flex-start' align='center'>
<Group gap="md" justify='center' align='center'>
{Object.entries(learningPaths).map(([learningPath, studies]) => {
return <AchievementBadge key={learningPath} learningPath={learningPath} studies={studies}/>
})}
Expand All @@ -205,7 +205,7 @@ const Achievements:FC = () => {
</Tabs.Panel>
</Tabs>
</Container>
<Footer />
<Footer /> </> : <LoadingAnimation />}
</Box>
);
};
Expand Down
102 changes: 58 additions & 44 deletions frontend/src/screens/learner.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { React, styled } from '@common'
import { useRef } from 'react'
import { ParticipantStudy } from '@api'
import { Footer, TopNavBar } from '@components'
import { useEnvironment, useIsMobileDevice } from '@lib'
import { Footer, TopNavBar, LoadingAnimation } from '@components'
import { useEnvironment, useIsMobileDevice, useIsTabletDevice } from '@lib'
import { useParticipantStudies, useSearchStudies } from './learner/studies'
import { StudyCard } from './learner/card'
import { StudyDetails } from './learner/details'
Expand All @@ -21,6 +21,7 @@ import StudyBanner from './studyBanner'
const HighlightedStudies: FC = () => {
const { highlightedStudies } = useParticipantStudies()
const isMobile = useIsMobileDevice()
const isTablet = useIsTabletDevice()

const scrollToStudies = () => {
const element = document.getElementById('all-studies-unique-id')
Expand All @@ -31,16 +32,13 @@ const HighlightedStudies: FC = () => {

return (
<Box bg={colors.navy} py='md'>
<Container>
<Container px={{ base: 16, sm: 32 }}>
<Stack>
<Group align='center' justify='space-between'>
{isMobile ?
<MobileStudyCards studies={highlightedStudies} /> :
<>
<CuratedStudies />
<div style={{ width: '70%' }}><DesktopStudyCards studies={highlightedStudies} /></div>
</>
}
<Group align='center' justify={isMobile? 'center' : isTablet? 'space-evenly' : 'space-between'}>
<CuratedStudies />
<Box w={isTablet || isMobile? '22.5rem' : '70%'}>
{isMobile || isTablet? <MobileStudyCards studies={highlightedStudies} /> : <DesktopStudyCards studies={highlightedStudies} />}
</Box>
</Group>
<Group c={colors.green} justify='center' align='center'>
<Stack justify='center' align='center' gap='0' style={{ cursor: 'pointer' }} onClick={()=> scrollToStudies()}>
Expand All @@ -56,12 +54,12 @@ const HighlightedStudies: FC = () => {

const CuratedStudies: FC = () => {
return (
<Stack c={colors.white} w='23%'>
<Stack c={colors.white} w="15rem" ta="left" style={{ hyphens: 'auto', wordBreak: 'break-word' }}>
<Title order={2}>Curated Studies</Title>
<Title order={5} mt='-1.2rem'>by our learning scientists</Title>

<Stack>
<Text pr='1.5rem'>Deepen your understanding of learning habits with scientific studies currated by our team of education researchers.</Text>
<Text>Deepen your understanding of learning habits with scientific studies currated by our team of education researchers.</Text>
<Text>Accelerate your growth and tailor your path to your own needs.</Text>
</Stack>
</Stack>
Expand Down Expand Up @@ -90,41 +88,43 @@ const LearnerDashboard = () => {
return () => window.removeEventListener('scroll', handleScroll);
}, []);

const { studies } = useParticipantStudies();


if (!env.isEligible) {
return <UnsupportedCountryModal />;
}

return (
<div className='studies learner' style={{ backgroundColor: colors.ash }}>
<div className='studies learner' style={{ backgroundColor: colors.ash, minHeight: '100vh' }}>
<Routes>
<Route path={'details/:studyId'} element={<StudyDetails />} />
</Routes>

<TopNavBar />
<StudyBanner />


<LearnerWelcomeModal />

<HighlightedStudies />
<StudiesContainer />
<Affix position={{ bottom: 20, left: 20 }}>
<IconCircleArrowUpFilled
ref={scrollButtonRef}
size='2rem'
onClick={scrollToTop}
style={{
display: 'none',
width: '30px',
height: '30px',
color: colors.purple,
cursor: 'pointer',
filter: 'drop-shadow(0px 4px 8px rgba(0, 0, 0, 0.1))',
}}
/>
</Affix>
<Footer includeFunders />
{studies.length > 0 ? <><StudyBanner />


<LearnerWelcomeModal />

<HighlightedStudies />
<StudiesContainer />
<Affix position={{ bottom: 20, left: 20 }}>
<IconCircleArrowUpFilled
ref={scrollButtonRef}
size='2rem'
onClick={scrollToTop}
style={{
display: 'none',
width: '30px',
height: '30px',
color: colors.purple,
cursor: 'pointer',
filter: 'drop-shadow(0px 4px 8px rgba(0, 0, 0, 0.1))',
}}
/>
</Affix>
<Footer includeFunders /></> : <LoadingAnimation />}
</div>
)
}
Expand Down Expand Up @@ -174,7 +174,7 @@ export const SearchBar: FC<{

export const StudiesTitle: FC<{search: string, filteredStudies: ParticipantStudy[]}> = () => {
return (
<Title order={2} id='all-studies-unique-id' style={{ paddingLeft: '2.5rem',paddingRight: '2.5rem' }}>View All Studies</Title>
<Title order={2} id='all-studies-unique-id'>View All Studies</Title>
)
}

Expand Down Expand Up @@ -284,8 +284,9 @@ const QuickLinks: FC<{filteredStudies: ParticipantStudy[]}> = ({ filteredStudies
return (
<Stack
w='25%'
p='1rem 1.5rem 1.5rem 2.5rem'
justify='flex-start'
pt="1rem"
pr="2.5rem"
gap='lg'
display={ isMobile? 'none' : 'flex' }
>
Expand Down Expand Up @@ -316,14 +317,16 @@ const QuickLinks: FC<{filteredStudies: ParticipantStudy[]}> = ({ filteredStudies

export const StudiesContainer = () => {
const { search, setSearch, duration, setDuration, filteredStudies } = useSearchStudies()
const isMobile = useIsMobileDevice()
const isTablet = useIsTabletDevice()

return (
<Container pt='1.5rem'>
<Container px={{ base: 16, sm: 32 }} pt='1.5rem'>
<Stack gap='lg'>
<StudiesTitle search={search} filteredStudies={filteredStudies} />
<Flex gap='xl'>
<QuickLinks filteredStudies={filteredStudies} />
<Stack w='75%' pl='1rem'>
{!isMobile && !isTablet ? <QuickLinks filteredStudies={filteredStudies} /> : ''}
<Stack w={!isMobile && !isTablet? '75%' : '100%'}>
<Group justify='space-between' wrap='wrap' pt='.5rem' pb='0.1rem'>
<Flex justify='center' align='center' gap='md'>
<StudyDuration duration={duration} durationText={5} setDuration={setDuration}></StudyDuration>
Expand All @@ -347,7 +350,18 @@ export const StudiesContainer = () => {
export const MobileStudyCards: FC<{studies: ParticipantStudy[]}> = ({ studies }) => {

return (
<Box>
<Box style={{ overflow: 'hidden' }}>
<style>
{`
.swiper-pagination-bullet {
background-color: ${colors.blue} !important;
}

.swiper-pagination-bullet-active {
background-color: ${colors.purple} !important;
}
`}
</style>
<Swiper
effect={'cards'}
slidesPerView={'auto'}
Expand All @@ -369,7 +383,7 @@ export const MobileStudyCards: FC<{studies: ParticipantStudy[]}> = ({ studies })
}}
>
{studies.map(study => (
<SwiperSlide key={study.id} className="pb-1" style={{ paddingTop: '1rem' }}>
<SwiperSlide key={study.id} className="pb-1" style={{ paddingTop: '1rem', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<StudyCard study={study}/>
</SwiperSlide>
))}
Expand Down
13 changes: 2 additions & 11 deletions frontend/src/screens/learner/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,9 @@ const Card = styled(Box)<{ studycompleted: boolean, multisession: boolean, color
maxHeight: 152,
},
[media.mobile]: {
minWidth: 275,
maxWidth: 275,
lineHeight: 1.2,
margin: '0 auto',
padding: '1rem',
minHeight: 360,
maxHeight: 360,
'.study-card-image': {
minHeight: '35%',
maxHeight: '35%',
height: '35%',
},
border: 'none',
boxShadow: '0px 4px 10px 0px rgba(0, 0, 0, 0.25)',
},
}))

Expand Down
26 changes: 14 additions & 12 deletions frontend/src/screens/studyBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useState, ReactNode } from 'react';
import { Stack, Title, Text, Anchor, Group, Container } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { IconArrowRight } from '@tabler/icons-react';
import { useIsMobileDevice, useIsTabletDevice } from '@lib';
import { useParticipantStudies, filterStudiesBasedOnDuration } from './learner/studies';
import { ParticipantStudy } from '@api';
import { launchStudy } from '@models';
Expand All @@ -21,30 +22,31 @@ const BannerSectionValue: FC<{children: ReactNode}> = ({ children }) => (
);

const BannerSectionText: FC<{children: ReactNode}> = ({ children }) => (
<Text c={colors.text} size="sm" w="80%">
<Text c={colors.text} size="sm">
{children}
</Text>
);

const BannerSectionLink: FC<{children: ReactNode, onClick: () => void}> = ({ children, ...props }) => (
<Anchor c={colors.blue} {...props}>
<Group gap="xs" justify='center' align='center'>
<Group gap={0} justify='center' align='center'>
<Text size="sm" fw={700}>{children}</Text>
<IconArrowRight size="1.2rem"/>
<IconArrowRight size="1.1rem"/>
</Group>
</Anchor>
);

const BannerSection: FC<{title: string, mainText: ReactNode, subText?: string, value?: string | number, onClick?: () => void}> = ({ title, mainText, subText, value, onClick }) => {
const hasValue = value !== undefined;
const isMobile = useIsMobileDevice()

return (
<Stack
gap={0}
justify='start'
align={hasValue? 'center' : 'start'}
w="30%"
h="6rem"
w={isMobile ? '12rem' : '10rem'}
h="5.75rem"
>
<BannerSectionTitle>{title}</BannerSectionTitle>
{hasValue ? (
Expand Down Expand Up @@ -113,10 +115,8 @@ const StudyBanner: React.FC = () => {
const formatValue = (value: number) => value.toString().padStart(2, '0');

const hasData = totalCompletedCount > 0 || badgesEarned > 0 || totalPointsEarned > 0;

if(studies.length <= 0){
return null;
}
const isMobile = useIsMobileDevice()
const isTablet = useIsTabletDevice()

return (
<Container pb="2rem" pt="2rem">
Expand All @@ -126,8 +126,10 @@ const StudyBanner: React.FC = () => {
wrap='wrap'
>
<Stack
justify='center'
w="20%"
justify='start'
align={hasData && isMobile? 'center' : 'start'}
ta={hasData && isMobile? 'center': 'left'}
w={isMobile ? '12rem' : isTablet ? '10rem' : '16.5rem'}
gap={0}
>
<Title order={3}>Achievements</Title>
Expand All @@ -137,7 +139,7 @@ const StudyBanner: React.FC = () => {
</Text>
</Stack>

<Group gap="md" w="60%" justify='center'>
<Group gap={isMobile? 'md' : 'xl'} justify='center' align='start'>
<BannerSection
title="Studies completed"
mainText={"You haven't completed any studies yet."}
Expand Down