🚸(frontend) enhance transcript copywritting
Simplify the instructions. Also offer a way to user to discover the feature and register as beta users.
This commit is contained in:
committed by
aleb_the_flash
parent
255da4bf60
commit
37fe23c0f7
@@ -1,10 +1,7 @@
|
|||||||
import { Button, Div, H, Text } from '@/primitives'
|
import { A, Button, Div, LinkButton, Text } from '@/primitives'
|
||||||
|
|
||||||
import thirdSlide from '@/assets/intro-slider/3_resume.png'
|
import thirdSlide from '@/assets/intro-slider/3_resume.png'
|
||||||
import { css } from '@/styled-system/css'
|
import { css } from '@/styled-system/css'
|
||||||
|
|
||||||
import { useHasTranscriptAccess } from '../hooks/useHasTranscriptAccess'
|
|
||||||
import { RiRecordCircleLine, RiStopCircleLine } from '@remixicon/react'
|
|
||||||
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
||||||
import { useRoomContext } from '@livekit/components-react'
|
import { useRoomContext } from '@livekit/components-react'
|
||||||
import {
|
import {
|
||||||
@@ -12,22 +9,34 @@ import {
|
|||||||
useStartRecording,
|
useStartRecording,
|
||||||
} from '@/features/rooms/api/startRecording'
|
} from '@/features/rooms/api/startRecording'
|
||||||
import { useStopRecording } from '@/features/rooms/api/stopRecording'
|
import { useStopRecording } from '@/features/rooms/api/stopRecording'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import { RoomEvent } from 'livekit-client'
|
import { RoomEvent } from 'livekit-client'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { NotificationPayload } from '@/features/notifications/NotificationPayload'
|
||||||
|
import { NotificationType } from '@/features/notifications/NotificationType'
|
||||||
|
import { useSnapshot } from 'valtio/index'
|
||||||
|
import {
|
||||||
|
TranscriptionStatus,
|
||||||
|
transcriptionStore,
|
||||||
|
} from '@/stores/transcription.ts'
|
||||||
|
import { useHasTranscriptAccess } from '../hooks/useHasTranscriptAccess'
|
||||||
|
import {
|
||||||
|
BETA_USERS_FORM_URL,
|
||||||
|
CRISP_HELP_ARTICLE_TRANSCRIPT,
|
||||||
|
} from '@/utils/constants'
|
||||||
|
|
||||||
export const Transcript = () => {
|
export const Transcript = () => {
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
|
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
|
||||||
|
|
||||||
const hasTranscriptAccess = useHasTranscriptAccess()
|
const hasTranscriptAccess = useHasTranscriptAccess()
|
||||||
|
|
||||||
const roomId = useRoomId()
|
const roomId = useRoomId()
|
||||||
|
|
||||||
const { mutateAsync: startRecordingRoom } = useStartRecording()
|
const { mutateAsync: startRecordingRoom } = useStartRecording()
|
||||||
const { mutateAsync: stopRecordingRoom } = useStopRecording()
|
const { mutateAsync: stopRecordingRoom } = useStopRecording()
|
||||||
|
|
||||||
|
const transcriptionSnap = useSnapshot(transcriptionStore)
|
||||||
|
|
||||||
const room = useRoomContext()
|
const room = useRoomContext()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -40,6 +49,17 @@ export const Transcript = () => {
|
|||||||
}
|
}
|
||||||
}, [room])
|
}, [room])
|
||||||
|
|
||||||
|
const notifyParticipant = async (status: NotificationType) => {
|
||||||
|
const encoder = new TextEncoder()
|
||||||
|
const payload: NotificationPayload = {
|
||||||
|
type: status,
|
||||||
|
}
|
||||||
|
const data = encoder.encode(JSON.stringify(payload))
|
||||||
|
await room.localParticipant.publishData(data, {
|
||||||
|
reliable: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleTranscript = async () => {
|
const handleTranscript = async () => {
|
||||||
if (!roomId) {
|
if (!roomId) {
|
||||||
console.warn('No room ID found')
|
console.warn('No room ID found')
|
||||||
@@ -49,8 +69,12 @@ export const Transcript = () => {
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
if (room.isRecording) {
|
if (room.isRecording) {
|
||||||
await stopRecordingRoom({ id: roomId })
|
await stopRecordingRoom({ id: roomId })
|
||||||
|
await notifyParticipant(NotificationType.TranscriptionStopped)
|
||||||
|
transcriptionStore.status = TranscriptionStatus.STOPPING
|
||||||
} else {
|
} else {
|
||||||
await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript })
|
await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript })
|
||||||
|
await notifyParticipant(NotificationType.TranscriptionStarted)
|
||||||
|
transcriptionStore.status = TranscriptionStatus.STARTING
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to handle transcript:', error)
|
console.error('Failed to handle transcript:', error)
|
||||||
@@ -58,7 +82,13 @@ export const Transcript = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasTranscriptAccess) return
|
const isDisabled = useMemo(
|
||||||
|
() =>
|
||||||
|
isLoading ||
|
||||||
|
transcriptionSnap.status === TranscriptionStatus.STARTING ||
|
||||||
|
transcriptionSnap.status === TranscriptionStatus.STOPPING,
|
||||||
|
[isLoading, transcriptionSnap]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Div
|
<Div
|
||||||
@@ -69,38 +99,98 @@ export const Transcript = () => {
|
|||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
>
|
>
|
||||||
<img src={thirdSlide} alt={'wip'} />
|
<img
|
||||||
{room.isRecording ? (
|
src={thirdSlide}
|
||||||
|
alt={''}
|
||||||
|
className={css({
|
||||||
|
minHeight: '309px',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
{!hasTranscriptAccess ? (
|
||||||
<>
|
<>
|
||||||
<H lvl={2}>{t('stop.heading')}</H>
|
<Text>{t('beta.heading')}</Text>
|
||||||
<Text variant="sm" centered wrap="balance">
|
<Text
|
||||||
{t('stop.body')}
|
variant="note"
|
||||||
</Text>
|
wrap={'pretty'}
|
||||||
<div className={css({ height: '2rem' })} />
|
centered
|
||||||
<Button
|
className={css({
|
||||||
isDisabled={isLoading}
|
textStyle: 'sm',
|
||||||
onPress={() => handleTranscript()}
|
marginBottom: '2.5rem',
|
||||||
data-attr="stop-transcript"
|
marginTop: '0.25rem',
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<RiStopCircleLine style={{ marginRight: '0.5rem' }} />{' '}
|
{t('beta.body')}{' '}
|
||||||
{t('stop.button')}
|
<A href={CRISP_HELP_ARTICLE_TRANSCRIPT} target="_blank">
|
||||||
</Button>
|
{t('start.linkMore')}
|
||||||
|
</A>
|
||||||
|
</Text>
|
||||||
|
<LinkButton
|
||||||
|
size="sm"
|
||||||
|
variant="tertiary"
|
||||||
|
href={BETA_USERS_FORM_URL}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{t('beta.button')}
|
||||||
|
</LinkButton>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<H lvl={2}>{t('start.heading')}</H>
|
{room.isRecording ? (
|
||||||
<Text variant="sm" centered wrap="balance">
|
<>
|
||||||
{t('start.body')}
|
<Text>{t('stop.heading')}</Text>
|
||||||
</Text>
|
<Text
|
||||||
<div className={css({ height: '2rem' })} />
|
variant="note"
|
||||||
<Button
|
wrap={'pretty'}
|
||||||
isDisabled={isLoading}
|
centered
|
||||||
onPress={() => handleTranscript()}
|
className={css({
|
||||||
data-attr="start-transcript"
|
textStyle: 'sm',
|
||||||
>
|
marginBottom: '2.5rem',
|
||||||
<RiRecordCircleLine style={{ marginRight: '0.5rem' }} />{' '}
|
marginTop: '0.25rem',
|
||||||
{t('start.button')}
|
})}
|
||||||
</Button>
|
>
|
||||||
|
{t('stop.body')}
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
onPress={() => handleTranscript()}
|
||||||
|
data-attr="stop-transcript"
|
||||||
|
size="sm"
|
||||||
|
variant="tertiary"
|
||||||
|
>
|
||||||
|
{t('stop.button')}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Text>{t('start.heading')}</Text>
|
||||||
|
<Text
|
||||||
|
variant="note"
|
||||||
|
wrap={'pretty'}
|
||||||
|
centered
|
||||||
|
className={css({
|
||||||
|
textStyle: 'sm',
|
||||||
|
maxWidth: '90%',
|
||||||
|
marginBottom: '2.5rem',
|
||||||
|
marginTop: '0.25rem',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{t('start.body')} <br />{' '}
|
||||||
|
<A href={CRISP_HELP_ARTICLE_TRANSCRIPT} target="_blank">
|
||||||
|
{t('start.linkMore')}
|
||||||
|
</A>
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
onPress={() => handleTranscript()}
|
||||||
|
data-attr="start-transcript"
|
||||||
|
size="sm"
|
||||||
|
variant="tertiary"
|
||||||
|
>
|
||||||
|
{t('start.button')}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Div>
|
</Div>
|
||||||
|
|||||||
@@ -199,12 +199,18 @@
|
|||||||
"start": {
|
"start": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
"body": "",
|
"body": "",
|
||||||
"button": ""
|
"button": "",
|
||||||
|
"linkMore": ""
|
||||||
},
|
},
|
||||||
"stop": {
|
"stop": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
"body": "",
|
"body": "",
|
||||||
"button": ""
|
"button": ""
|
||||||
|
},
|
||||||
|
"beta": {
|
||||||
|
"heading": "",
|
||||||
|
"body": "",
|
||||||
|
"button": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@@ -196,14 +196,20 @@
|
|||||||
},
|
},
|
||||||
"transcript": {
|
"transcript": {
|
||||||
"start": {
|
"start": {
|
||||||
"heading": "Start the Assistant!",
|
"heading": "Transcribe this call",
|
||||||
"body": "The assistant automatically starts recording your meeting audio (limited to 1 hour). At the end, you'll receive a clear and concise summary of the discussion directly via email.",
|
"body": "Automatically transcribe this call and receive the summary in Docs.",
|
||||||
"button": "Start"
|
"button": "Start transcription",
|
||||||
|
"linkMore": "Learn more"
|
||||||
},
|
},
|
||||||
"stop": {
|
"stop": {
|
||||||
"heading": "Recording in Progress...",
|
"heading": "Transcription in progress...",
|
||||||
"body": "Your meeting is currently being recorded. You will receive a summary via email once the meeting ends.",
|
"body": "The transcription of your meeting is in progress. You will receive the result by email once the meeting is finished.",
|
||||||
"button": "Stop Recording"
|
"button": "Stop transcription"
|
||||||
|
},
|
||||||
|
"beta": {
|
||||||
|
"heading": "Become a beta tester",
|
||||||
|
"body": "Record your meeting for later. You will receive a summary by email once the meeting is finished.",
|
||||||
|
"button": "Sign up"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@@ -196,14 +196,20 @@
|
|||||||
},
|
},
|
||||||
"transcript": {
|
"transcript": {
|
||||||
"start": {
|
"start": {
|
||||||
"heading": "Démarrer l'assistant !",
|
"heading": "Transcrire cet appel",
|
||||||
"body": "L'assistant démarre automatiquement l'enregistrement sonore de votre réunion (limité à 1h). À la fin, vous recevrez un résumé clair et concis des échanges directement par e-mail.",
|
"body": "Transcrivez cet appel automatiquement et recevez le compte rendu dans Docs.",
|
||||||
"button": "Démarrer"
|
"button": "Démarrer la transcription",
|
||||||
|
"linkMore": "En savoir plus"
|
||||||
},
|
},
|
||||||
"stop": {
|
"stop": {
|
||||||
"heading": "Enregistrement en cours …",
|
"heading": "Transcription en cours …",
|
||||||
"body": "L'enregistrement de votre réunion est en cours. Vous recevrez un compte-rendu par email une fois la réunion terminée.",
|
"body": "La transcription de votre réunion est en cours. Vous recevrez le resultat par email une fois la réunion terminée.",
|
||||||
"button": "Arrêter l'enregistrement"
|
"button": "Arrêter la transcription"
|
||||||
|
},
|
||||||
|
"beta": {
|
||||||
|
"heading": "Devenez beta testeur",
|
||||||
|
"body": "Enregistrer votre réunion pour plus tard. Vous recevrez un compte-rendu par email une fois la réunion terminée.",
|
||||||
|
"button": "Inscrivez-vous"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@@ -196,14 +196,20 @@
|
|||||||
},
|
},
|
||||||
"transcript": {
|
"transcript": {
|
||||||
"start": {
|
"start": {
|
||||||
"heading": "Start de assistent!",
|
"heading": "Transcribeer dit gesprek",
|
||||||
"body": "De assistent begint automatisch de audio van uw vergadering op te nemen (beperkt tot 1 uur). Na afloop krijgt u direct een heldere en beknopte samenvatting van de discussies in uw e-mail.",
|
"body": "Transcribeer dit gesprek automatisch en ontvang het verslag in Docs.",
|
||||||
"button": "Start"
|
"button": "Transcriptie starten",
|
||||||
|
"linkMore": "Meer informatie"
|
||||||
},
|
},
|
||||||
"stop": {
|
"stop": {
|
||||||
"heading": "Opname loopt ...",
|
"heading": "Transcriptie bezig...",
|
||||||
"body": "Uw vergadering wordt momenteel opgenomen. U ontvangt een samenvatting via e-mail, zo gauw de vergarding gesloten wordt.",
|
"body": "De transcriptie van uw vergadering is bezig. U ontvangt het resultaat per e-mail zodra de vergadering is afgelopen.",
|
||||||
"button": "Stop met opname"
|
"button": "Transcriptie stoppen"
|
||||||
|
},
|
||||||
|
"beta": {
|
||||||
|
"heading": "Word betatester",
|
||||||
|
"body": "Neem uw vergadering op voor later. U ontvangt een samenvatting per e-mail zodra de vergadering is afgelopen.",
|
||||||
|
"button": "Aanmelden"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@@ -6,3 +6,6 @@ export const BETA_USERS_FORM_URL =
|
|||||||
|
|
||||||
export const CRISP_HELP_ARTICLE_MORE_TOOLS =
|
export const CRISP_HELP_ARTICLE_MORE_TOOLS =
|
||||||
'https://lasuite.crisp.help/fr/article/visio-tools-bvxj23' as const
|
'https://lasuite.crisp.help/fr/article/visio-tools-bvxj23' as const
|
||||||
|
|
||||||
|
export const CRISP_HELP_ARTICLE_TRANSCRIPT =
|
||||||
|
'https://lasuite.crisp.help/fr/article/visio-transcript-1sjq43x' as const
|
||||||
|
|||||||
Reference in New Issue
Block a user