diff --git a/components/cards/AccountActionsCard.tsx b/components/cards/AccountActionsCard.tsx
index 975e91391..7515df41f 100644
--- a/components/cards/AccountActionsCard.tsx
+++ b/components/cards/AccountActionsCard.tsx
@@ -83,10 +83,8 @@ const AccountActionsCard = () => {
id="delete-account-button"
variant="outlined"
sx={{
- border: `solid 2px ${theme.palette.primary.dark}`,
color: theme.palette.primary.dark,
'&:hover': {
- border: `solid 2px ${theme.palette.primary.dark}`,
background: theme.palette.primary.dark,
color: theme.palette.common.white,
},
diff --git a/components/course/CourseHeader.tsx b/components/course/CourseHeader.tsx
index 6fe3b4c27..489fb0ce1 100644
--- a/components/course/CourseHeader.tsx
+++ b/components/course/CourseHeader.tsx
@@ -7,6 +7,14 @@ import { EventUserData } from '../../utils/logEvent';
import Link from '../common/Link';
import Header from '../layout/Header';
+const buttonStyle = {
+ background: theme.palette.background.default,
+ boxShadow: 'none !important',
+ ':hover': {
+ background: 'white',
+ },
+} as const;
+
export interface CourseHeaderProps {
name: string;
description: ISbRichtext;
@@ -29,13 +37,7 @@ const CourseHeader = (props: CourseHeaderProps) => {
return (
diff --git a/components/layout/Footer.tsx b/components/layout/Footer.tsx
index ec873bb73..575f18c07 100644
--- a/components/layout/Footer.tsx
+++ b/components/layout/Footer.tsx
@@ -190,7 +190,7 @@ const Footer = () => {
alt={tS(partner.logoAlt)}
src={partner.logo}
fill
- sizes="100vw"
+ sizes="300px"
style={{
objectFit: 'contain',
objectPosition: 'left',
diff --git a/components/layout/TopBar.tsx b/components/layout/TopBar.tsx
index ae4f2d4cd..d412d2876 100644
--- a/components/layout/TopBar.tsx
+++ b/components/layout/TopBar.tsx
@@ -82,7 +82,7 @@ const TopBar = () => {
alt={tS('alt.bloomLogo')}
src={bloomLogo}
fill
- sizes="100vw"
+ sizes="250px"
style={{
objectFit: 'contain',
}}
diff --git a/components/resources/ResourceCompleteButton.tsx b/components/resources/ResourceCompleteButton.tsx
index 4c7950c7c..308ddfc9a 100644
--- a/components/resources/ResourceCompleteButton.tsx
+++ b/components/resources/ResourceCompleteButton.tsx
@@ -22,13 +22,14 @@ const errorStyle = {
} as const;
interface ResourceCompleteButtonProps {
+ resourceName: string;
category: RESOURCE_CATEGORIES;
storyId: number;
eventData: EventUserData;
}
export const ResourceCompleteButton = (props: ResourceCompleteButtonProps) => {
- const { category, storyId, eventData } = props;
+ const { resourceName, category, storyId, eventData } = props;
const t = useTranslations('Resources');
@@ -79,7 +80,7 @@ export const ResourceCompleteButton = (props: ResourceCompleteButtonProps) => {
}
>
diff --git a/components/resources/ResourceConversationAudio.tsx b/components/resources/ResourceConversationAudio.tsx
new file mode 100644
index 000000000..3ea892c7c
--- /dev/null
+++ b/components/resources/ResourceConversationAudio.tsx
@@ -0,0 +1,144 @@
+import { Link, Typography } from '@mui/material';
+import { ISbRichtext } from '@storyblok/react';
+import { useTranslations } from 'next-intl';
+import { useCallback, useEffect, useState } from 'react';
+import { PROGRESS_STATUS } from '../../constants/enums';
+import {
+ RESOURCE_CONVERSATION_COMPLETE_ERROR,
+ RESOURCE_CONVERSATION_COMPLETE_REQUEST,
+ RESOURCE_CONVERSATION_COMPLETE_SUCCESS,
+ RESOURCE_CONVERSATION_STARTED_ERROR,
+ RESOURCE_CONVERSATION_STARTED_REQUEST,
+ RESOURCE_CONVERSATION_STARTED_SUCCESS,
+ RESOURCE_CONVERSATION_TRANSCRIPT_CLOSED,
+ RESOURCE_CONVERSATION_TRANSCRIPT_OPENED,
+} from '../../constants/events';
+import { useTypedSelector } from '../../hooks/store';
+import { useCompleteResourceMutation, useStartResourceMutation } from '../../store/api';
+import logEvent, { EventUserData } from '../../utils/logEvent';
+import Audio from '../video/Audio';
+import VideoTranscriptModal from '../video/VideoTranscriptModal';
+
+export interface EventData extends EventUserData {
+ resource_name: string;
+ resource_storyblok_id: number;
+ resource_progress: PROGRESS_STATUS;
+}
+
+interface ResourceConversationAudioProps {
+ eventData: EventData;
+ resourceProgress: PROGRESS_STATUS;
+ name: string;
+ storyId: number;
+ audio: string;
+ audio_transcript: ISbRichtext;
+}
+
+export const ResourceConversationAudio = (props: ResourceConversationAudioProps) => {
+ const { eventData, storyId, resourceProgress, name, audio_transcript, audio } = props;
+ const [openTranscriptModal, setOpenTranscriptModal] = useState(null);
+ const [startResourceConversation] = useStartResourceMutation();
+ const [completeResourceConversation] = useCompleteResourceMutation();
+ const isLoggedIn = useTypedSelector((state) => Boolean(state.user.id));
+
+ const t = useTranslations('Resources');
+
+ const callStartResourceConversation = useCallback(async () => {
+ logEvent(RESOURCE_CONVERSATION_STARTED_REQUEST, eventData);
+
+ const startResourceConversationResponse = await startResourceConversation({
+ storyblokId: storyId,
+ });
+
+ if (startResourceConversationResponse.data) {
+ logEvent(RESOURCE_CONVERSATION_STARTED_SUCCESS, eventData);
+ }
+
+ if (startResourceConversationResponse.error) {
+ const error = startResourceConversationResponse.error;
+
+ logEvent(RESOURCE_CONVERSATION_STARTED_ERROR, eventData);
+ (window as any).Rollbar?.error('ResourceConversation started error', error);
+
+ throw error;
+ }
+ }, [startResourceConversation, eventData, name, storyId]);
+
+ const callCompleteResourceConversation = useCallback(async () => {
+ logEvent(RESOURCE_CONVERSATION_COMPLETE_REQUEST, eventData);
+
+ const completeResourceConversationResponse = await completeResourceConversation({
+ storyblokId: storyId,
+ });
+
+ if (completeResourceConversationResponse.data) {
+ logEvent(RESOURCE_CONVERSATION_COMPLETE_SUCCESS, eventData);
+ }
+
+ if (completeResourceConversationResponse.error) {
+ const error = completeResourceConversationResponse.error;
+
+ logEvent(RESOURCE_CONVERSATION_COMPLETE_ERROR, eventData);
+ (window as any).Rollbar?.error('ResourceConversation completed error', error);
+
+ throw error;
+ }
+ }, [completeResourceConversation, eventData, name, storyId]);
+
+ useEffect(() => {
+ if (openTranscriptModal === null) return;
+
+ logEvent(
+ openTranscriptModal
+ ? RESOURCE_CONVERSATION_TRANSCRIPT_OPENED
+ : RESOURCE_CONVERSATION_TRANSCRIPT_CLOSED,
+ eventData,
+ );
+ if (isLoggedIn && openTranscriptModal && resourceProgress === PROGRESS_STATUS.NOT_STARTED) {
+ callStartResourceConversation();
+ }
+ }, [
+ callStartResourceConversation,
+ openTranscriptModal,
+ eventData,
+ name,
+ resourceProgress,
+ isLoggedIn,
+ ]);
+
+ const audioStarted = () => {
+ if (isLoggedIn && resourceProgress === PROGRESS_STATUS.NOT_STARTED) {
+ callStartResourceConversation();
+ }
+ };
+
+ const audioFinished = () => {
+ if (isLoggedIn && resourceProgress !== PROGRESS_STATUS.COMPLETED) {
+ callCompleteResourceConversation();
+ }
+ };
+
+ return (
+ <>
+
+
+ {t.rich('conversationTranscriptLink', {
+ link: (children) => setOpenTranscriptModal(true)}>{children},
+ })}
+
+
+
+ >
+ );
+};
diff --git a/components/resources/ResourceShortVideo.tsx b/components/resources/ResourceShortVideo.tsx
index 3756413b0..2d4ca976b 100644
--- a/components/resources/ResourceShortVideo.tsx
+++ b/components/resources/ResourceShortVideo.tsx
@@ -1,7 +1,7 @@
import { Link, Typography } from '@mui/material';
import { ISbRichtext } from '@storyblok/react';
import { useTranslations } from 'next-intl';
-import { useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
import { PROGRESS_STATUS } from '../../constants/enums';
import {
RESOURCE_SHORT_VIDEO_COMPLETE_ERROR,
@@ -12,8 +12,8 @@ import {
RESOURCE_SHORT_VIDEO_STARTED_SUCCESS,
RESOURCE_SHORT_VIDEO_TRANSCRIPT_CLOSED,
RESOURCE_SHORT_VIDEO_TRANSCRIPT_OPENED,
- RESOURCE_SHORT_VIDEO_VIEWED,
} from '../../constants/events';
+import { useTypedSelector } from '../../hooks/store';
import { useCompleteResourceMutation, useStartResourceMutation } from '../../store/api';
import logEvent, { EventUserData } from '../../utils/logEvent';
import Video from '../video/Video';
@@ -36,18 +36,15 @@ interface ResourceShortVideoProps {
export const ResourceShortVideo = (props: ResourceShortVideoProps) => {
const { eventData, storyId, resourceProgress, name, video_transcript, video } = props;
- const [videoStarted, setVideoStarted] = useState(false);
- const [videoFinished, setVideoFinished] = useState(false);
const [openTranscriptModal, setOpenTranscriptModal] = useState(null);
const [startResourceShort] = useStartResourceMutation();
const [completeResourceShort] = useCompleteResourceMutation();
+ const isLoggedIn = useTypedSelector((state) => Boolean(state.user.id));
+
const t = useTranslations('Resources');
- async function callStartResourceShort() {
- logEvent(RESOURCE_SHORT_VIDEO_STARTED_REQUEST, {
- ...eventData,
- resource_name: name,
- });
+ const callStartResourceShort = useCallback(async () => {
+ logEvent(RESOURCE_SHORT_VIDEO_STARTED_REQUEST, eventData);
const startResourceShortResponse = await startResourceShort({
storyblokId: storyId,
@@ -65,13 +62,10 @@ export const ResourceShortVideo = (props: ResourceShortVideoProps) => {
throw error;
}
- }
+ }, [startResourceShort, eventData, storyId]);
- async function callCompleteResourceShort() {
- logEvent(RESOURCE_SHORT_VIDEO_COMPLETE_REQUEST, {
- ...eventData,
- resource_name: name,
- });
+ const callCompleteResourceShort = useCallback(async () => {
+ logEvent(RESOURCE_SHORT_VIDEO_COMPLETE_REQUEST, eventData);
const completeResourceShortResponse = await completeResourceShort({
storyblokId: storyId,
@@ -89,7 +83,7 @@ export const ResourceShortVideo = (props: ResourceShortVideoProps) => {
throw error;
}
- }
+ }, [completeResourceShort, eventData, storyId]);
useEffect(() => {
if (openTranscriptModal === null) return;
@@ -98,50 +92,38 @@ export const ResourceShortVideo = (props: ResourceShortVideoProps) => {
openTranscriptModal
? RESOURCE_SHORT_VIDEO_TRANSCRIPT_OPENED
: RESOURCE_SHORT_VIDEO_TRANSCRIPT_CLOSED,
- {
- ...eventData,
- resource_name: name,
- course_name: name,
- },
+ eventData,
);
- if (openTranscriptModal && resourceProgress === PROGRESS_STATUS.NOT_STARTED) {
+ if (isLoggedIn && openTranscriptModal && resourceProgress === PROGRESS_STATUS.NOT_STARTED) {
callStartResourceShort();
}
- }, [openTranscriptModal, eventData, name, resourceProgress]);
-
- useEffect(() => {
- if (!videoStarted || resourceProgress !== PROGRESS_STATUS.NOT_STARTED) return;
+ }, [callStartResourceShort, openTranscriptModal, eventData, name, resourceProgress, isLoggedIn]);
- if (videoStarted) {
+ const videoStarted = () => {
+ if (isLoggedIn && resourceProgress === PROGRESS_STATUS.NOT_STARTED) {
callStartResourceShort();
}
- }, [videoStarted, resourceProgress]);
+ };
- useEffect(() => {
- if (!videoFinished || resourceProgress === PROGRESS_STATUS.COMPLETED) return;
-
- if (videoFinished) {
+ const videoFinished = () => {
+ if (isLoggedIn && resourceProgress !== PROGRESS_STATUS.COMPLETED) {
callCompleteResourceShort();
}
- }, [videoFinished, resourceProgress]);
-
- useEffect(() => {
- logEvent(RESOURCE_SHORT_VIDEO_VIEWED, eventData);
- }, []);
+ };
return (
video && (
<>
- {t.rich('transcriptLink', {
+ {t.rich('videoTranscriptLink', {
link: (children) => (
setOpenTranscriptModal(true)}>{children}
),
diff --git a/components/session/SessionHeader.tsx b/components/session/SessionHeader.tsx
index ced771652..0dd6b2a62 100644
--- a/components/session/SessionHeader.tsx
+++ b/components/session/SessionHeader.tsx
@@ -9,6 +9,14 @@ import theme from '../../styles/theme';
import Link from '../common/Link';
import Header from '../layout/Header';
+const buttonStyle = {
+ background: theme.palette.background.default,
+ boxShadow: 'none !important',
+ ':hover': {
+ background: 'white',
+ },
+} as const;
+
const sessionSubtitleStyle = {
marginTop: '0.75rem !important',
} as const;
@@ -58,21 +66,15 @@ export const SessionHeader = (props: SessionHeaderProps) => {
imageAlt={headerProps.imageAlt}
progressStatus={sessionProgress}
>
-