Skip to content

Commit

Permalink
fix: breadcrumb buttons, german activity related content, user resear…
Browse files Browse the repository at this point in the history
…ch banner (#1298)
  • Loading branch information
annarhughes authored Feb 7, 2025
1 parent 19cf466 commit e6898b2
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 232 deletions.
4 changes: 2 additions & 2 deletions app/[locale]/shorts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ export default async function Page({ params }: { params: Params }) {
story?.content.related_session[0].content.course,
);

if (!story) {
if (!story || !relatedCourse) {
notFound();
}

return (
<StoryblokResourceShortPage
{...(story.content as StoryblokResourceShortPageProps)}
related_course={relatedCourse ? relatedCourse[0] : undefined}
related_course={relatedCourse[0]}
storyId={story.id}
/>
);
Expand Down
18 changes: 8 additions & 10 deletions components/course/CourseHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,11 @@
import Header from '@/components/layout/Header';
import { Link as i18nLink } from '@/i18n/routing';
import { PROGRESS_STATUS } from '@/lib/constants/enums';
import theme from '@/styles/theme';
import { breadcrumbButtonStyle } from '@/styles/common';
import { Button } from '@mui/material';
import { ISbRichtext } from '@storyblok/react/rsc';
import { useTranslations } from 'next-intl';

const buttonStyle = {
background: theme.palette.background.default,
boxShadow: 'none !important',
':hover': {
background: 'white',
},
} as const;

interface CourseHeaderProps {
name: string;
description: ISbRichtext;
Expand All @@ -39,7 +31,13 @@ const CourseHeader = (props: CourseHeaderProps) => {

return (
<Header {...headerProps}>
<Button variant="outlined" sx={buttonStyle} href="/courses" component={i18nLink} size="small">
<Button
variant="contained"
sx={breadcrumbButtonStyle}
href="/courses"
component={i18nLink}
size="small"
>
{t('backToCourses')}
</Button>
</Header>
Expand Down
2 changes: 0 additions & 2 deletions components/layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import UserResearchBanner from '@/components/banner/UserResearchBanner';
import ProgressStatus from '@/components/common/ProgressStatus';
import { useRouter } from '@/i18n/routing';
import { PROGRESS_STATUS } from '@/lib/constants/enums';
Expand Down Expand Up @@ -107,7 +106,6 @@ const Header = (props: HeaderProps) => {

return (
<Container sx={headerContainerStyle}>
<UserResearchBanner />
<Box sx={textContainerStyle}>
<IconButton
sx={backButtonStyle}
Expand Down
2 changes: 0 additions & 2 deletions components/layout/HomeHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import UserResearchBanner from '@/components/banner/UserResearchBanner';
import { getImageSizes } from '@/lib/utils/imageSizes';
import { RichTextOptions } from '@/lib/utils/richText';
import { columnStyle, rowStyle } from '@/styles/common';
Expand Down Expand Up @@ -75,7 +74,6 @@ const Header = (props: HeaderProps) => {

return (
<Container sx={headerContainerStyles}>
<UserResearchBanner />
<Box sx={textContainerStyle}>
<Box sx={textContentStyle}>
<Typography variant="h1" component="h1" mb={3}>
Expand Down
2 changes: 0 additions & 2 deletions components/layout/PartnerHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import UserResearchBanner from '@/components/banner/UserResearchBanner';
import { getImageSizes } from '@/lib/utils/imageSizes';
import { rowStyle } from '@/styles/common';
import { Box, Container } from '@mui/material';
Expand Down Expand Up @@ -43,7 +42,6 @@ const PartnerHeader = (props: HeaderProps) => {

return (
<Container sx={headerContainerStyles}>
<UserResearchBanner />
<Box sx={logoContainerStyle}>
<Image
alt={tS(partnerLogoAlt)}
Expand Down
41 changes: 33 additions & 8 deletions components/pages/CoursesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ import { ShortsCard } from '@/components/cards/ShortsCard';
import Carousel, { getSlideWidth } from '@/components/common/Carousel';
import Column from '@/components/common/Column';
import LoadingContainer from '@/components/common/LoadingContainer';
import PageSection from '@/components/common/PageSection';
import Row from '@/components/common/Row';
import Header from '@/components/layout/Header';
import {
EMAIL_REMINDERS_FREQUENCY,
PROGRESS_STATUS,
RESOURCE_CATEGORIES,
STORYBLOK_COLORS,
} from '@/lib/constants/enums';
import { COURSE_LIST_VIEWED } from '@/lib/constants/events';
import { useTypedSelector } from '@/lib/hooks/store';
import { getDefaultFullSlug } from '@/lib/utils/getDefaultFullSlug';
import logEvent from '@/lib/utils/logEvent';
import userHasAccessToPartnerContent from '@/lib/utils/userHasAccessToPartnerContent';
import illustrationCourses from '@/public/illustration_courses.svg';
import { Box, Container, Grid, Typography } from '@mui/material';
import theme from '@/styles/theme';
import { Box, Container, Grid, Typography, useMediaQuery } from '@mui/material';
import { ISbStoryData } from '@storyblok/react/rsc';
import Cookies from 'js-cookie';
import { useLocale, useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useSearchParams } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';

const containerStyle = {
backgroundColor: 'secondary.light',
Expand Down Expand Up @@ -57,6 +57,10 @@ export default function CoursesPage({ courseStories, conversations, shorts }: Pr
const partnerAccesses = useTypedSelector((state) => state.partnerAccesses);
const partnerAdmin = useTypedSelector((state) => state.partnerAdmin);
const courses = useTypedSelector((state) => state.courses);
const searchParams = useSearchParams();
const sectionQueryParam = searchParams.get('section');
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const headerOffset = isSmallScreen ? 48 : 136;

const t = useTranslations('Courses');

Expand All @@ -71,6 +75,27 @@ export default function CoursesPage({ courseStories, conversations, shorts }: Pr
logEvent(COURSE_LIST_VIEWED);
}, []);

const setShortsSectionRef = useCallback(
(node: HTMLDivElement | null) => {
if (!node) return;
if (sectionQueryParam === 'shorts' && node && loadedCourses) {
const scrollToY = node.getBoundingClientRect().top + window.scrollY - headerOffset;
window.scrollTo({ top: scrollToY, behavior: 'smooth' });
}
},
[sectionQueryParam, headerOffset, loadedCourses],
);

const setConversationsSectionRef = useCallback(
(node: HTMLDivElement | null) => {
if (sectionQueryParam === 'conversations' && node && loadedCourses) {
const scrollToY = node.getBoundingClientRect().top + window.scrollY - headerOffset;
window.scrollTo({ top: scrollToY, behavior: 'smooth' });
}
},
[sectionQueryParam, headerOffset, loadedCourses],
);

useEffect(() => {
if (
userEmailRemindersFrequency &&
Expand Down Expand Up @@ -173,7 +198,7 @@ export default function CoursesPage({ courseStories, conversations, shorts }: Pr
)}
</Container>
{conversations.length > 0 && (
<PageSection color={STORYBLOK_COLORS.SECONDARY_MAIN} alignment="left">
<Container sx={{ backgroundColor: 'secondary.main' }} ref={setConversationsSectionRef}>
<Row numberOfColumns={1} horizontalAlignment="left" verticalAlignment="center">
<Column width="full-width">
<Typography variant="h2" fontWeight={500}>
Expand Down Expand Up @@ -211,10 +236,10 @@ export default function CoursesPage({ courseStories, conversations, shorts }: Pr
/>
</Column>
</Row>
</PageSection>
</Container>
)}
{loadedShorts && loadedShorts?.length > 0 && (
<PageSection color={STORYBLOK_COLORS.SECONDARY_LIGHT} alignment="left">
<Container sx={{ backgroundColor: 'secondary.light' }} ref={setShortsSectionRef}>
<Row numberOfColumns={1} horizontalAlignment="left" verticalAlignment="center">
<Column width="full-width">
<Typography variant="h2" fontWeight={500}>
Expand Down Expand Up @@ -247,7 +272,7 @@ export default function CoursesPage({ courseStories, conversations, shorts }: Pr
/>
</Column>
</Row>
</PageSection>
</Container>
)}

{!userId && <SignUpBanner />}
Expand Down
76 changes: 76 additions & 0 deletions components/resources/ResourceConversationHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use client';

import Header from '@/components/layout/Header';
import { ResourceConversationAudio } from '@/components/resources/ResourceConversationAudio';
import { Link as i18nLink } from '@/i18n/routing';
import { PROGRESS_STATUS } from '@/lib/constants/enums';
import { RichTextOptions } from '@/lib/utils/richText';
import illustrationCourses from '@/public/illustration_courses.svg';
import { breadcrumbButtonStyle } from '@/styles/common';
import { Box, Button } from '@mui/material';
import { ISbRichtext } from '@storyblok/react/rsc';
import { useTranslations } from 'next-intl';
import { render } from 'storyblok-rich-text-react-renderer';

const audioContainerStyle = {
mt: { xs: 4, md: 6 },
mb: 3,
} as const;

interface ResourceConversationHeaderProps {
storyId: number;
name: string;
description: ISbRichtext;
header_image: { filename: string; alt: string };
resourceProgress: PROGRESS_STATUS;
audio: { filename: string };
audio_transcript: ISbRichtext;
eventData: { [key: string]: any };
}

export const ResourceConversationHeader = (props: ResourceConversationHeaderProps) => {
const {
storyId,
name,
description,
header_image,
resourceProgress,
audio,
audio_transcript,
eventData,
} = props;
const t = useTranslations('Resources');

return (
<Header
title={name}
introduction={
<Box display="flex" flexDirection="column" gap={3}>
{render(description, RichTextOptions)}
<Box sx={audioContainerStyle}>
<ResourceConversationAudio
eventData={eventData}
resourceProgress={resourceProgress}
name={name}
storyId={storyId}
audio={audio.filename}
audio_transcript={audio_transcript}
/>
</Box>
</Box>
}
imageSrc={header_image ? header_image.filename : illustrationCourses}
progressStatus={resourceProgress}
>
<Button
variant="contained"
sx={breadcrumbButtonStyle}
href="/courses?section=conversations"
component={i18nLink}
size="small"
>
{t('backToConversations')}
</Button>
</Header>
);
};
119 changes: 119 additions & 0 deletions components/resources/ResourceShortsHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use client';

import ProgressStatus from '@/components/common/ProgressStatus';
import { ResourceShortVideo } from '@/components/resources/ResourceShortVideo';
import { Link as i18nLink } from '@/i18n/routing';
import { COURSE_CATEGORIES, PROGRESS_STATUS } from '@/lib/constants/enums';
import { RESOURCE_SHORT_VIDEO_VISIT_SESSION } from '@/lib/constants/events';
import { getDefaultFullSlug } from '@/lib/utils/getDefaultFullSlug';
import logEvent from '@/lib/utils/logEvent';
import { breadcrumbButtonStyle, columnStyle, rowStyle } from '@/styles/common';
import theme from '@/styles/theme';
import { Box, Button, Container, Typography } from '@mui/material';
import { ISbRichtext, ISbStoryData } from '@storyblok/react/rsc';
import { useLocale, useTranslations } from 'next-intl';

const headerStyle = { ...rowStyle, flexWrap: { xs: 'wrap', md: 'no-wrap' }, gap: 5 } as const;
const headerRightStyle = {
...columnStyle,
justifyContent: 'flex-end',
flex: { md: 1 },
width: { md: '100%' },
height: { md: 290 },
} as const;

const headerLeftStyles = {
width: 514, // >515px enables the "watch on youtube" button
maxWidth: '100%',
} as const;

interface ResourceShortHeaderProps {
storyId: number;
name: string;
resourceProgress: PROGRESS_STATUS;
relatedSession: ISbStoryData;
relatedCourse: ISbStoryData;
video: { url: string };
video_transcript: ISbRichtext;
eventData: { [key: string]: any };
}

export const ResourceShortHeader = (props: ResourceShortHeaderProps) => {
const {
storyId,
name,
relatedSession,
relatedCourse,
resourceProgress,
video,
video_transcript,
eventData,
} = props;
const t = useTranslations('Resources');
const locale = useLocale();

const redirectToSession = () => {
logEvent(RESOURCE_SHORT_VIDEO_VISIT_SESSION, {
...eventData,
shorts_name: name,
session_name: relatedSession?.name,
});
};

return (
<Container sx={{ background: theme.palette.bloomGradient }}>
<Button
variant="contained"
sx={{ ...breadcrumbButtonStyle, mb: 4 }}
href="/courses?section=shorts"
component={i18nLink}
size="small"
>
{t('backToShorts')}
</Button>
<Typography variant="h1" maxWidth={600}>
{name}
</Typography>
<Box sx={headerStyle}>
<Box sx={headerLeftStyles}>
<ResourceShortVideo
eventData={eventData}
resourceProgress={resourceProgress}
name={name}
storyId={storyId}
video={video}
video_transcript={video_transcript}
/>
{resourceProgress && <ProgressStatus status={resourceProgress} />}
</Box>
{relatedSession && (
<Box sx={headerRightStyle}>
{/* Description field is not currently displayed */}
{/* {render(description, RichTextOptions)} */}

<Typography component="h2" mb={2}>
{t('sessionDetail', {
sessionNumber:
relatedSession.content.component === COURSE_CATEGORIES.COURSE
? 0
: relatedSession.position / 10 - 1,
sessionName: relatedSession.content.name,
courseName: relatedCourse?.content.name,
})}
</Typography>
<Button
href={getDefaultFullSlug(relatedSession.full_slug, locale)}
component={i18nLink}
onClick={redirectToSession}
variant="contained"
color="secondary"
sx={{ mr: 'auto' }}
>
{t('sessionButtonLabel')}
</Button>
</Box>
)}
</Box>
</Container>
);
};
Loading

0 comments on commit e6898b2

Please sign in to comment.