Merge pull request #722 from omnivore-app/OMN-696
[OMN-696]: Subscribe to checked newsletters during onboarding
This commit is contained in:
@ -4,7 +4,7 @@ import { VStack, HStack, Box } from '../elements/LayoutPrimitives'
|
||||
import { OmnivoreNameLogo } from '../elements/images/OmnivoreNameLogo'
|
||||
import { StyledText } from '../elements/StyledText'
|
||||
import { Button } from '../elements/Button'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const TOTAL_ONBOARDING_PAGES = 6
|
||||
|
||||
@ -17,6 +17,7 @@ type OnboardingLayoutProps = {
|
||||
image?: ReactNode
|
||||
nextPage?: string,
|
||||
reduceSpace?: boolean,
|
||||
onNext?: () => void | Promise<void>,
|
||||
}
|
||||
|
||||
export const OnboardingLayout = ({
|
||||
@ -27,30 +28,36 @@ export const OnboardingLayout = ({
|
||||
image,
|
||||
children,
|
||||
nextPage,
|
||||
reduceSpace
|
||||
reduceSpace,
|
||||
onNext,
|
||||
}: OnboardingLayoutProps) => {
|
||||
const NextButton = () => (
|
||||
<Link href={nextPage ? nextPage : `/onboarding/0${pageNumber+1}`}>
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
css={{
|
||||
width: '111px',
|
||||
height: '44px',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
textDecoration: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
as="a"
|
||||
href={nextPage ? nextPage : `/onboarding/0${pageNumber+1}`}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</Link>
|
||||
)
|
||||
const router = useRouter()
|
||||
|
||||
const NextButton = () => {
|
||||
const handleNext = async () => {
|
||||
onNext && await onNext()
|
||||
router.push(nextPage ?? `/onboarding/0${pageNumber+1}`)
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
css={{
|
||||
width: '111px',
|
||||
height: '44px',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
textDecoration: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
onClick={handleNext}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
)}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -1,28 +1,37 @@
|
||||
import React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { subscribeMutation } from '../../../lib/networking/mutations/subscribeMutation'
|
||||
import { VStack } from '../../elements/LayoutPrimitives'
|
||||
import { OnboardingLayout } from '../OnboardingLayout'
|
||||
import { SelectOption } from './SelectOption'
|
||||
|
||||
const optionDetails = [
|
||||
const newsletterOptions = [
|
||||
{
|
||||
icon: 'AxiosDaily.png',
|
||||
label: 'Axios Daily Essentials',
|
||||
description: 'Start and end your day with the stories that matter in your inbox.'
|
||||
description: 'Start and end your day with the stories that matter in your inbox.',
|
||||
name: 'axios_essentials',
|
||||
isChecked: false,
|
||||
},
|
||||
{
|
||||
icon: 'MilkRoad.png',
|
||||
label: 'Milk Road',
|
||||
description: '5 minute daily newsletter. Used by 100,000+ people to be better crypto investors 💪',
|
||||
name: 'morning_brew',
|
||||
isChecked: false,
|
||||
},
|
||||
{
|
||||
icon: 'MoneyStuff.png',
|
||||
label: 'Money Stuff by Matt Levine',
|
||||
description: 'A daily take on Wall Street, finance, companies and other stuff.',
|
||||
name: 'milk_road',
|
||||
isChecked: false,
|
||||
},
|
||||
{
|
||||
icon: 'OmnivoreBlog.png',
|
||||
label: 'Omnivore',
|
||||
description: 'Tips and tricks, plus updates on new features in Omnivore.',
|
||||
name: 'omnivore_blog',
|
||||
isChecked: false,
|
||||
},
|
||||
]
|
||||
|
||||
@ -30,20 +39,48 @@ type OnboardingAddNewslettersProps = {
|
||||
pageNumber: number
|
||||
}
|
||||
|
||||
export type NewsLetterOption = {
|
||||
icon: string,
|
||||
label: string,
|
||||
name: string,
|
||||
description: string,
|
||||
isChecked: boolean,
|
||||
}
|
||||
|
||||
export const OnboardingAddNewsletters = (props: OnboardingAddNewslettersProps) => {
|
||||
|
||||
const [newsletters, setNewsletters] = useState<NewsLetterOption[]>(newsletterOptions);
|
||||
|
||||
const onCheck = (index: number) => {
|
||||
const temp = [...newsletters]
|
||||
temp[index].isChecked = !temp[index].isChecked
|
||||
setNewsletters(temp)
|
||||
}
|
||||
|
||||
const onNext = () => {
|
||||
newsletters.map((newsletter) => {
|
||||
if (newsletter.isChecked) subscribeMutation(newsletter.name)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<OnboardingLayout
|
||||
pageNumber={props.pageNumber}
|
||||
subTitle="Omnivore creates an email address for you to subscribe to newsletters with."
|
||||
description="Subscribe to some newsletters now"
|
||||
title="Read all your Newsletters in Omnivore"
|
||||
onNext={onNext}
|
||||
>
|
||||
<VStack css={{
|
||||
marginTop: '$4',
|
||||
width: '100%'
|
||||
}}>
|
||||
{optionDetails.map(({ icon, label, description }, idx) => (
|
||||
<SelectOption key={idx} {...{ icon, label, description }} />
|
||||
{newsletters.map(({ icon, label, description, isChecked }, idx) => (
|
||||
<SelectOption
|
||||
key={idx}
|
||||
indexNum={idx}
|
||||
onCheck={onCheck}
|
||||
{...{ icon, label, description, isChecked}} />
|
||||
))}
|
||||
</VStack>
|
||||
</OnboardingLayout>
|
||||
|
||||
@ -12,15 +12,19 @@ export const SelectOption: React.FC<{
|
||||
icon: string
|
||||
label: string
|
||||
description: string
|
||||
}> = ({ icon, label, description }) => {
|
||||
const [checked, setChecked] = React.useState(false)
|
||||
onCheck: (idx: number) => void
|
||||
indexNum: number
|
||||
isChecked: boolean
|
||||
}> = ({ icon, label, description, onCheck, indexNum, isChecked}) => {
|
||||
|
||||
const toggleChecked = () => setChecked(!checked)
|
||||
const toggleChecked = () => {
|
||||
onCheck(indexNum)
|
||||
}
|
||||
|
||||
return (
|
||||
<HStack onClick={toggleChecked} css={{
|
||||
border: checked ? '1px solid #F9D354' : '1px solid #0000000F',
|
||||
backgroundColor: checked ? '#FDFAEC' : '#FFFFFF',
|
||||
border: isChecked ? '1px solid #F9D354' : '1px solid #0000000F',
|
||||
backgroundColor: isChecked ? '#FDFAEC' : '#FFFFFF',
|
||||
boxShadow: '0px 3px 11px 0px #201F1D0A',
|
||||
justifyContent: 'flex-start',
|
||||
alignItems: 'center',
|
||||
@ -30,7 +34,7 @@ export const SelectOption: React.FC<{
|
||||
marginBottom: 7,
|
||||
width: '100%'
|
||||
}}>
|
||||
<Checkbox {...{checked, setChecked}} />
|
||||
<Checkbox checked={isChecked} setChecked={() => undefined} />
|
||||
<SpanBox css={{ marginLeft: '$2', width: '32px', height: '32px' }}>
|
||||
<Image width={32} height={32} layout="fixed"
|
||||
src={`/static/images/newsletter/${icon}`}
|
||||
|
||||
38
packages/web/lib/networking/mutations/subscribeMutation.ts
Normal file
38
packages/web/lib/networking/mutations/subscribeMutation.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { gql } from 'graphql-request'
|
||||
import { gqlFetcher } from '../networkHelpers'
|
||||
import { Subscription } from '../queries/useGetSubscriptionsQuery'
|
||||
|
||||
type SubscribeResult = {
|
||||
subscribe: Subscribe
|
||||
errorCodes?: unknown[]
|
||||
}
|
||||
|
||||
type Subscribe = {
|
||||
subscriptions: Subscription[]
|
||||
}
|
||||
|
||||
export async function subscribeMutation(
|
||||
subscribeName: string
|
||||
): Promise<any | undefined> {
|
||||
const mutation = gql`
|
||||
mutation {
|
||||
subscribe(name: "${subscribeName}") {
|
||||
... on SubscribeSuccess {
|
||||
subscriptions {
|
||||
id
|
||||
}
|
||||
}
|
||||
... on SubscribeError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
try {
|
||||
const data = (await gqlFetcher(mutation)) as SubscribeResult
|
||||
return data.errorCodes ? undefined : data.subscribe
|
||||
} catch (error) {
|
||||
console.log('subscribeMutation error', error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user