Skip to content

Commit

Permalink
fix(onboarding-flow): implement onboarding functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
aliraza556 committed Oct 26, 2024
1 parent da36774 commit d0105fd
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/components/App/Splash/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { Text } from '~/components/common/Text'
import { getAboutData, getSchemaAll, getStats } from '~/network/fetchSourcesData'
import { useAppStore } from '~/stores/useAppStore'
import { useDataStore } from '~/stores/useDataStore'
import { useModal } from '~/stores/useModalStore'
import { useSchemaStore } from '~/stores/useSchemaStore'
import { useUserStore } from '~/stores/useUserStore'
import { colors, formatSplashMessage, formatStatsResponse } from '~/utils'
import { AnimatedTextContent } from './animated'
import { initialMessageData, Message } from './constants'
Expand All @@ -19,6 +21,8 @@ export const Splash = () => {
const { appMetaData, setAppMetaData } = useAppStore((s) => s)
const { stats, setStats, setSeedQuestions } = useDataStore((s) => s)
const { schemas, setSchemas } = useSchemaStore((s) => s)
const { isAdmin } = useUserStore((s) => s)
const { open, visible } = useModal('onboardingFlow')
const [isLoading, setIsLoading] = useState(false)

// Individual useEffect hooks for each data requirement
Expand Down Expand Up @@ -63,6 +67,12 @@ export const Splash = () => {
}
}, [appMetaData, isLoading, schemas.length, setAppMetaData, setSchemas, setSeedQuestions, setStats, stats])

useEffect(() => {
if (!isLoading && isAdmin && !appMetaData?.title && !visible) {
open()
}
}, [isLoading, isAdmin, appMetaData?.title, open, visible])

useEffect(() => {
const fetchSchemas = async () => {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { Button } from '@mui/material'
import { FC, useEffect } from 'react'
import { useFormContext } from 'react-hook-form'
import { MdError } from 'react-icons/md'
import styled from 'styled-components'
import { noSpacePattern } from '~/components/AddItemModal/SourceTypeStep/constants'
import { Flex } from '~/components/common/Flex'
import { Text } from '~/components/common/Text'
import { TextInput } from '~/components/common/TextInput'
import { requiredRule } from '~/constants'
import { colors } from '~/utils'

type Props = {
onSubmit: () => void
error?: string
}

export const GraphDetailsStep: FC<Props> = ({ onSubmit, error }) => {
const {
formState: { isSubmitting },
watch,
} = useFormContext()

const title = watch('title')
const description = watch('description')

const isFormValid = !!title?.trim() && !!description?.trim()

useEffect(() => {
const titleInput = document.getElementById('graph-title') as HTMLInputElement

if (titleInput) {
titleInput.focus()
}
}, [])

return (
<Flex>
<Flex align="center" direction="column" justify="center">
<StyledText>Welcome to SecondBrain!</StyledText>
<StyledSubText>Set a name and short description for your graph.</StyledSubText>
</Flex>

<StyledWrapper>
<Flex className="input__wrapper">
<TextInput
id="graph-title"
label="Title"
maxLength={50}
name="title"
placeholder="Type graph title here..."
rules={{
...requiredRule,
pattern: {
message: 'No leading whitespace allowed',
value: noSpacePattern,
},
}}
/>
<TextInput
id="graph-description"
label="Description"
maxLength={100}
name="description"
placeholder="Type graph description here..."
rules={{
...requiredRule,
pattern: {
message: 'No leading whitespace allowed',
value: noSpacePattern,
},
}}
/>
</Flex>
</StyledWrapper>

<Flex mt={10}>
<Button
color="secondary"
disabled={isSubmitting || !!error || !isFormValid}
onClick={onSubmit}
size="large"
variant="contained"
>
Confirm
</Button>
</Flex>
{error ? (
<StyledError>
<StyledErrorText>
<MdError className="errorIcon" />
<span>{error}</span>
</StyledErrorText>
</StyledError>
) : null}
</Flex>
)
}

const StyledText = styled(Text)`
font-size: 22px;
font-weight: 600;
font-family: 'Barlow';
text-align: center;
margin-bottom: 10px;
`

const StyledSubText = styled(Text)`
font-size: 14px;
font-family: 'Barlow';
margin-bottom: 20px;
`

const StyledWrapper = styled(Flex)`
width: 100%;
display: flex;
justify-content: center;
gap: 10px;
margin: 0 0 15px 0;
.input__wrapper {
display: flex;
gap: 23px;
max-height: 225px;
overflow-y: auto;
padding-right: 20px;
width: calc(100% + 20px);
}
`

const StyledErrorText = styled(Flex)`
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 2px;
.errorIcon {
display: block;
font-size: 13px;
min-height: 13px;
min-width: 13px;
}
span {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
white-space: normal;
letter-spacing: 0.2px;
padding-left: 4px;
font-size: 13px;
font-family: Barlow;
line-height: 18px;
}
`

const StyledError = styled(Flex)`
display: flex;
align-items: center;
color: ${colors.primaryRed};
position: relative;
margin-top: 20px;
`
71 changes: 71 additions & 0 deletions src/components/ModalsContainer/OnboardingFlow/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useEffect, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { SuccessNotify } from '~/components/common/SuccessToast'
import { BaseModal } from '~/components/Modal'
import { NODE_ADD_ERROR } from '~/constants'
import { postAboutData, TAboutParams } from '~/network/fetchSourcesData'
import { useModal } from '~/stores/useModalStore'
import { GraphDetailsStep } from './GraphDetailsStep'

export type FormData = {
title: string
description: string
}

export const OnboardingModal = () => {
const { close, visible } = useModal('onboardingFlow')
const form = useForm<FormData>({ mode: 'onChange' })
const { reset } = form
const [error, setError] = useState<string>('')

useEffect(() => {
if (!visible) {
reset()
setError('')
}
}, [visible, reset])

const submitGraphDetails = async (data: TAboutParams, onSuccess: () => void, onError: (error: string) => void) => {
try {
const res = (await postAboutData(data)) as Awaited<{ status: string }>

if (res.status === 'success') {
SuccessNotify('Graph details saved')
onSuccess()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
let errorMessage = NODE_ADD_ERROR

if (err?.status === 400) {
const errorRes = await err.json()

errorMessage = errorRes.errorCode || errorRes?.status || NODE_ADD_ERROR
} else if (err instanceof Error) {
errorMessage = err.message
}

onError(String(errorMessage))
}
}

const onSubmit = form.handleSubmit(async (data) => {
await submitGraphDetails(
data,
() => {
close()
},
setError,
)
})

return (
<BaseModal id="onboardingFlow" kind="small" onClose={close} preventOutsideClose>
<FormProvider {...form}>
<form id="onboardingFlow-form" onSubmit={onSubmit}>
<GraphDetailsStep error={error} onSubmit={onSubmit} />
</form>
</FormProvider>
</BaseModal>
)
}
5 changes: 5 additions & 0 deletions src/components/ModalsContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const LazyCreateBountyModal = lazy(() =>
import('./CreateBountyModal').then(({ CreateBountyModal }) => ({ default: CreateBountyModal })),
)

const LazyOnboardingModal = lazy(() =>
import('./OnboardingFlow').then(({ OnboardingModal }) => ({ default: OnboardingModal })),
)

export const ModalsContainer = () => (
<>
<LazyAddItemModal />
Expand All @@ -60,5 +64,6 @@ export const ModalsContainer = () => (
<LazyMergeNodeModal />
<LazyUserFeedBackModal />
<LazyCreateBountyModal />
<LazyOnboardingModal />
</>
)
2 changes: 2 additions & 0 deletions src/stores/useModalStore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type AvailableModals =
| 'changeNodeType'
| 'feedback'
| 'createBounty'
| 'onboardingFlow'

type ModalStore = {
currentModals: Record<AvailableModals, boolean>
Expand Down Expand Up @@ -51,6 +52,7 @@ const defaultData = {
changeNodeType: false,
feedback: false,
createBounty: false,
onboardingFlow: false,
},
}

Expand Down

0 comments on commit d0105fd

Please sign in to comment.