Delete onboarding-wizard

environments/review-onboarding-kw1bfz/deployments/4764
danidfra 2024-08-15 14:16:37 -03:00
rodzic f71abb4543
commit 2146d5ea03
8 zmienionych plików z 0 dodań i 829 usunięć

Wyświetl plik

@ -1,119 +0,0 @@
import clsx from 'clsx';
import React from 'react';
import ReactSwipeableViews from 'react-swipeable-views';
import { endOnboarding } from 'soapbox/actions/onboarding';
import LandingGradient from 'soapbox/components/landing-gradient';
import { HStack } from 'soapbox/components/ui';
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
import AvatarSelectionStep from './steps/avatar-selection-step';
import BioStep from './steps/bio-step';
import CompletedStep from './steps/completed-step';
import CoverPhotoSelectionStep from './steps/cover-photo-selection-step';
import DisplayNameStep from './steps/display-name-step';
import FediverseStep from './steps/fediverse-step';
import SuggestedAccountsStep from './steps/suggested-accounts-step';
const OnboardingWizard = () => {
const dispatch = useAppDispatch();
const features = useFeatures();
const [currentStep, setCurrentStep] = React.useState<number>(0);
const handleSwipe = (nextStep: number) => {
setCurrentStep(nextStep);
};
const handlePreviousStep = () => {
setCurrentStep((prevStep) => Math.max(0, prevStep - 1));
};
const handleNextStep = () => {
setCurrentStep((prevStep) => Math.min(prevStep + 1, steps.length - 1));
};
const handleComplete = () => {
dispatch(endOnboarding());
};
const steps = [
<AvatarSelectionStep onNext={handleNextStep} />,
<DisplayNameStep onNext={handleNextStep} />,
<BioStep onNext={handleNextStep} />,
<CoverPhotoSelectionStep onNext={handleNextStep} />,
<SuggestedAccountsStep onNext={handleNextStep} />,
];
if (features.federating && !features.nostr) {
steps.push(<FediverseStep onNext={handleNextStep} />);
}
steps.push(<CompletedStep onComplete={handleComplete} />);
const handleKeyUp = ({ key }: KeyboardEvent): void => {
switch (key) {
case 'ArrowLeft':
handlePreviousStep();
break;
case 'ArrowRight':
handleNextStep();
break;
}
};
const handleDotClick = (nextStep: number) => {
setCurrentStep(nextStep);
};
React.useEffect(() => {
document.addEventListener('keyup', handleKeyUp);
return () => {
document.removeEventListener('keyup', handleKeyUp);
};
}, []);
return (
<div data-testid='onboarding-wizard'>
<LandingGradient />
<main className='flex h-screen flex-col overflow-x-hidden'>
<div className='flex h-full flex-col items-center justify-center'>
<ReactSwipeableViews animateHeight index={currentStep} onChangeIndex={handleSwipe}>
{steps.map((step, i) => (
<div key={i} className='w-full max-w-[100vw] py-6 sm:mx-auto sm:max-w-lg md:max-w-2xl'>
<div
className={clsx({
'transition-opacity ease-linear': true,
'opacity-0 duration-500': currentStep !== i,
'opacity-100 duration-75': currentStep === i,
})}
>
{step}
</div>
</div>
))}
</ReactSwipeableViews>
<HStack space={3} alignItems='center' justifyContent='center' className='relative'>
{steps.map((_, i) => (
<button
key={i}
tabIndex={0}
onClick={() => handleDotClick(i)}
className={clsx({
'w-5 h-5 rounded-full focus:ring-primary-600 focus:ring-2 focus:ring-offset-2': true,
'bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-700/75 hover:bg-gray-400': i !== currentStep,
'bg-primary-600': i === currentStep,
})}
/>
))}
</HStack>
</div>
</main>
</div>
);
};
export default OnboardingWizard;

Wyświetl plik

@ -1,125 +0,0 @@
import clsx from 'clsx';
import React from 'react';
import { defineMessages, FormattedMessage } from 'react-intl';
import { patchMe } from 'soapbox/actions/me';
import { endOnboarding } from 'soapbox/actions/onboarding';
import { BigCard } from 'soapbox/components/big-card';
import { Avatar, Button, Icon, Spinner, Stack } from 'soapbox/components/ui';
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
import toast from 'soapbox/toast';
import { isDefaultAvatar } from 'soapbox/utils/accounts';
import resizeImage from 'soapbox/utils/resize-image';
import type { AxiosError } from 'axios';
const messages = defineMessages({
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
});
const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
const dispatch = useAppDispatch();
const { account } = useOwnAccount();
const fileInput = React.useRef<HTMLInputElement>(null);
const [selectedFile, setSelectedFile] = React.useState<string | null>();
const [isSubmitting, setSubmitting] = React.useState<boolean>(false);
const [isDisabled, setDisabled] = React.useState<boolean>(true);
const isDefault = account ? isDefaultAvatar(account.avatar) : false;
const openFilePicker = () => {
fileInput.current?.click();
};
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const maxPixels = 400 * 400;
const rawFile = event.target.files?.item(0);
if (!rawFile) return;
resizeImage(rawFile, maxPixels).then((file) => {
const url = file ? URL.createObjectURL(file) : account?.avatar as string;
setSelectedFile(url);
setSubmitting(true);
const formData = new FormData();
formData.append('avatar', rawFile);
const credentials = dispatch(patchMe(formData));
Promise.all([credentials]).then(() => {
setDisabled(false);
setSubmitting(false);
onNext();
}).catch((error: AxiosError) => {
setSubmitting(false);
setDisabled(false);
setSelectedFile(null);
if (error.response?.status === 422) {
toast.error((error.response.data as any).error.replace('Validation failed: ', ''));
} else {
toast.error(messages.error);
}
});
}).catch(console.error);
};
const handleComplete = () => {
dispatch(endOnboarding());
};
return (
<BigCard
title={<FormattedMessage id='onboarding.avatar.title' defaultMessage='Choose a profile picture' />}
subtitle={<FormattedMessage id='onboarding.avatar.subtitle' defaultMessage='Just have fun with it.' />}
onClose={handleComplete}
>
<Stack space={10}>
<div className='relative mx-auto rounded-full bg-gray-200'>
{account && (
<Avatar src={selectedFile || account.avatar} size={175} />
)}
{isSubmitting && (
<div className='absolute inset-0 flex items-center justify-center rounded-full bg-white/80 dark:bg-primary-900/80'>
<Spinner withText={false} />
</div>
)}
<button
onClick={openFilePicker}
type='button'
className={clsx({
'absolute bottom-3 right-2 p-1 bg-primary-600 rounded-full ring-2 ring-white dark:ring-primary-900 hover:bg-primary-700': true,
'opacity-50 pointer-events-none': isSubmitting,
})}
disabled={isSubmitting}
>
<Icon src={require('@tabler/icons/outline/plus.svg')} className='h-5 w-5 text-white' />
</button>
<input type='file' className='hidden' ref={fileInput} onChange={handleFileChange} />
</div>
<Stack justifyContent='center' space={2}>
<Button block theme='primary' type='button' onClick={onNext} disabled={isDefault && isDisabled || isSubmitting}>
{isSubmitting ? (
<FormattedMessage id='onboarding.saving' defaultMessage='Saving…' />
) : (
<FormattedMessage id='onboarding.next' defaultMessage='Next' />
)}
</Button>
{isDisabled && (
<Button block theme='tertiary' type='button' onClick={onNext}>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
</Button>
)}
</Stack>
</Stack>
</BigCard>
);
};
export default AvatarSelectionStep;

Wyświetl plik

@ -1,99 +0,0 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { patchMe } from 'soapbox/actions/me';
import { endOnboarding } from 'soapbox/actions/onboarding';
import { BigCard } from 'soapbox/components/big-card';
import { Button, FormGroup, Stack, Textarea } from 'soapbox/components/ui';
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
import toast from 'soapbox/toast';
import type { AxiosError } from 'axios';
const messages = defineMessages({
bioPlaceholder: { id: 'onboarding.bio.placeholder', defaultMessage: 'Tell the world a little about yourself…' },
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
});
const BioStep = ({ onNext }: { onNext: () => void }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { account } = useOwnAccount();
const [value, setValue] = React.useState<string>(account?.source?.note ?? '');
const [isSubmitting, setSubmitting] = React.useState<boolean>(false);
const [errors, setErrors] = React.useState<string[]>([]);
const handleSubmit = () => {
setSubmitting(true);
const credentials = dispatch(patchMe({ note: value }));
Promise.all([credentials])
.then(() => {
setSubmitting(false);
onNext();
}).catch((error: AxiosError) => {
setSubmitting(false);
if (error.response?.status === 422) {
setErrors([(error.response.data as any).error.replace('Validation failed: ', '')]);
} else {
toast.error(messages.error);
}
});
};
const handleComplete = () => {
dispatch(endOnboarding());
};
return (
<BigCard
title={<FormattedMessage id='onboarding.note.title' defaultMessage='Write a short bio' />}
subtitle={<FormattedMessage id='onboarding.note.subtitle' defaultMessage='You can always edit this later.' />}
onClose={handleComplete}
>
<Stack space={5}>
<div>
<FormGroup
hintText={<FormattedMessage id='onboarding.bio.hint' defaultMessage='Max 500 characters' />}
labelText={<FormattedMessage id='edit_profile.fields.bio_label' defaultMessage='Bio' />}
errors={errors}
>
<Textarea
onChange={(event) => setValue(event.target.value)}
placeholder={intl.formatMessage(messages.bioPlaceholder)}
value={value}
maxLength={500}
/>
</FormGroup>
</div>
<div>
<Stack justifyContent='center' space={2}>
<Button
block
theme='primary'
type='submit'
disabled={isSubmitting}
onClick={handleSubmit}
>
{isSubmitting ? (
<FormattedMessage id='onboarding.saving' defaultMessage='Saving…' />
) : (
<FormattedMessage id='onboarding.next' defaultMessage='Next' />
)}
</Button>
<Button block theme='tertiary' type='button' onClick={onNext}>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
</Button>
</Stack>
</div>
</Stack>
</BigCard>
);
};
export default BioStep;

Wyświetl plik

@ -1,39 +0,0 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, Card, CardBody, Icon, Stack, Text } from 'soapbox/components/ui';
const CompletedStep = ({ onComplete }: { onComplete: () => void }) => (
<Card variant='rounded' size='xl'>
<CardBody>
<Stack space={2}>
<Icon strokeWidth={1} src={require('@tabler/icons/outline/confetti.svg')} className='mx-auto h-16 w-16 text-primary-600 dark:text-primary-400' />
<Text size='2xl' align='center' weight='bold'>
<FormattedMessage id='onboarding.finished.title' defaultMessage='Onboarding complete' />
</Text>
<Text theme='muted' align='center'>
<FormattedMessage
id='onboarding.finished.message'
defaultMessage='We are very excited to welcome you to our community! Tap the button below to get started.'
/>
</Text>
</Stack>
<div className='mx-auto pt-10 sm:w-2/3 md:w-1/2'>
<Stack justifyContent='center' space={2}>
<Button
block
theme='primary'
onClick={onComplete}
>
<FormattedMessage id='onboarding.view_feed' defaultMessage='View Feed' />
</Button>
</Stack>
</div>
</CardBody>
</Card>
);
export default CompletedStep;

Wyświetl plik

@ -1,149 +0,0 @@
import clsx from 'clsx';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { patchMe } from 'soapbox/actions/me';
import { endOnboarding } from 'soapbox/actions/onboarding';
import { BigCard } from 'soapbox/components/big-card';
import StillImage from 'soapbox/components/still-image';
import { Avatar, Button, Icon, Spinner, Stack, Text } from 'soapbox/components/ui';
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
import toast from 'soapbox/toast';
import { isDefaultHeader } from 'soapbox/utils/accounts';
import resizeImage from 'soapbox/utils/resize-image';
import type { AxiosError } from 'axios';
const messages = defineMessages({
header: { id: 'account.header.alt', defaultMessage: 'Profile header' },
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
});
const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { account } = useOwnAccount();
const fileInput = React.useRef<HTMLInputElement>(null);
const [selectedFile, setSelectedFile] = React.useState<string | null>();
const [isSubmitting, setSubmitting] = React.useState<boolean>(false);
const [isDisabled, setDisabled] = React.useState<boolean>(true);
const isDefault = account ? isDefaultHeader(account.header) : false;
const openFilePicker = () => {
fileInput.current?.click();
};
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const maxPixels = 1920 * 1080;
const rawFile = event.target.files?.item(0);
if (!rawFile) return;
resizeImage(rawFile, maxPixels).then((file) => {
const url = file ? URL.createObjectURL(file) : account?.header as string;
setSelectedFile(url);
setSubmitting(true);
const formData = new FormData();
formData.append('header', file);
const credentials = dispatch(patchMe(formData));
Promise.all([credentials]).then(() => {
setDisabled(false);
setSubmitting(false);
onNext();
}).catch((error: AxiosError) => {
setSubmitting(false);
setDisabled(false);
setSelectedFile(null);
if (error.response?.status === 422) {
toast.error((error.response.data as any).error.replace('Validation failed: ', ''));
} else {
toast.error(messages.error);
}
});
}).catch(console.error);
};
const handleComplete = () => {
dispatch(endOnboarding());
};
return (
<BigCard
title={<FormattedMessage id='onboarding.header.title' defaultMessage='Pick a cover image' />}
subtitle={<FormattedMessage id='onboarding.header.subtitle' defaultMessage='This will be shown at the top of your profile.' />}
onClose={handleComplete}
>
<Stack space={10}>
<div className='rounded-lg border border-solid border-gray-200 dark:border-gray-800'>
<div
role='button'
className='relative flex h-24 items-center justify-center rounded-t-md bg-gray-200 dark:bg-gray-800'
>
<div className='flex h-24 w-full overflow-hidden rounded-t-md'>
{selectedFile || account?.header && (
<StillImage
src={selectedFile || account.header}
alt={intl.formatMessage(messages.header)}
className='absolute inset-0 w-full rounded-t-md object-cover'
/>
)}
</div>
{isSubmitting && (
<div
className='absolute inset-0 flex items-center justify-center rounded-t-md bg-white/80 dark:bg-primary-900/80'
>
<Spinner withText={false} />
</div>
)}
<button
onClick={openFilePicker}
type='button'
className={clsx({
'absolute -top-3 -right-3 p-1 bg-primary-600 rounded-full ring-2 ring-white dark:ring-primary-900 hover:bg-primary-700': true,
'opacity-50 pointer-events-none': isSubmitting,
})}
disabled={isSubmitting}
>
<Icon src={require('@tabler/icons/outline/plus.svg')} className='h-5 w-5 text-white' />
</button>
<input type='file' className='hidden' ref={fileInput} onChange={handleFileChange} />
</div>
<div className='flex flex-col px-4 pb-4'>
{account && (
<Avatar src={account.avatar} size={64} className='-mt-8 mb-2 ring-2 ring-white dark:ring-primary-800' />
)}
<Text weight='bold' size='sm'>{account?.display_name}</Text>
<Text theme='muted' size='sm'>@{account?.username}</Text>
</div>
</div>
<Stack justifyContent='center' space={2}>
<Button block theme='primary' type='button' onClick={onNext} disabled={isDefault && isDisabled || isSubmitting}>
{isSubmitting ? (
<FormattedMessage id='onboarding.saving' defaultMessage='Saving…' />
) : (
<FormattedMessage id='onboarding.next' defaultMessage='Next' />
)}
</Button>
{isDisabled && (
<Button block theme='tertiary' type='button' onClick={onNext}>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
</Button>
)}
</Stack>
</Stack>
</BigCard>
);
};
export default CoverPhotoSelectionStep;

Wyświetl plik

@ -1,107 +0,0 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { patchMe } from 'soapbox/actions/me';
import { endOnboarding } from 'soapbox/actions/onboarding';
import { BigCard } from 'soapbox/components/big-card';
import { Button, FormGroup, Input, Stack } from 'soapbox/components/ui';
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
import toast from 'soapbox/toast';
import type { AxiosError } from 'axios';
const messages = defineMessages({
usernamePlaceholder: { id: 'onboarding.display_name.placeholder', defaultMessage: 'Eg. John Smith' },
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
});
const DisplayNameStep = ({ onNext }: { onNext: () => void }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { account } = useOwnAccount();
const [value, setValue] = React.useState<string>(account?.display_name || '');
const [isSubmitting, setSubmitting] = React.useState<boolean>(false);
const [errors, setErrors] = React.useState<string[]>([]);
const trimmedValue = value.trim();
const isValid = trimmedValue.length > 0;
const isDisabled = !isValid || value.length > 30;
const hintText = React.useMemo(() => {
const charsLeft = 30 - value.length;
const suffix = charsLeft === 1 ? 'character remaining' : 'characters remaining';
return `${charsLeft} ${suffix}`;
}, [value]);
const handleSubmit = () => {
setSubmitting(true);
const credentials = dispatch(patchMe({ display_name: value }));
Promise.all([credentials])
.then(() => {
setSubmitting(false);
onNext();
}).catch((error: AxiosError) => {
setSubmitting(false);
if (error.response?.status === 422) {
setErrors([(error.response.data as any).error.replace('Validation failed: ', '')]);
} else {
toast.error(messages.error);
}
});
};
const handleComplete = () => {
dispatch(endOnboarding());
};
return (
<BigCard
title={<FormattedMessage id='onboarding.display_name.title' defaultMessage='Choose a display name' />}
subtitle={<FormattedMessage id='onboarding.display_name.subtitle' defaultMessage='You can always edit this later.' />}
onClose={handleComplete}
>
<Stack space={5}>
<FormGroup
hintText={hintText}
labelText={<FormattedMessage id='onboarding.display_name.label' defaultMessage='Display name' />}
errors={errors}
>
<Input
onChange={(event) => setValue(event.target.value)}
placeholder={intl.formatMessage(messages.usernamePlaceholder)}
type='text'
value={value}
maxLength={30}
/>
</FormGroup>
<Stack justifyContent='center' space={2}>
<Button
block
theme='primary'
type='submit'
disabled={isDisabled || isSubmitting}
onClick={handleSubmit}
>
{isSubmitting ? (
<FormattedMessage id='onboarding.saving' defaultMessage='Saving…' />
) : (
<FormattedMessage id='onboarding.next' defaultMessage='Next' />
)}
</Button>
<Button block theme='tertiary' type='button' onClick={onNext}>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
</Button>
</Stack>
</Stack>
</BigCard>
);
};
export default DisplayNameStep;

Wyświetl plik

@ -1,88 +0,0 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Account from 'soapbox/components/account';
import { Button, Card, CardBody, Icon, Stack, Text } from 'soapbox/components/ui';
import { useInstance, useOwnAccount } from 'soapbox/hooks';
const FediverseStep = ({ onNext }: { onNext: () => void }) => {
const { account } = useOwnAccount();
const instance = useInstance();
return (
<Card variant='rounded' size='xl'>
<CardBody>
<Stack space={2}>
<Icon strokeWidth={1} src={require('@tabler/icons/outline/affiliate.svg')} className='mx-auto h-16 w-16 text-primary-600 dark:text-primary-400' />
<Text size='2xl' weight='bold'>
<FormattedMessage
id='onboarding.fediverse.title'
defaultMessage='{siteTitle} is just one part of the Fediverse'
values={{
siteTitle: instance.title,
}}
/>
</Text>
<Stack space={4}>
<div className='border-b border-solid border-gray-200 pb-2 sm:pb-5 dark:border-gray-800'>
<Stack space={4}>
<Text theme='muted'>
<FormattedMessage
id='onboarding.fediverse.message'
defaultMessage='The Fediverse is a social network made up of thousands of diverse and independently-run social media sites (aka "servers"). You can follow users — and like, repost, and reply to posts — from most other Fediverse servers, because they can communicate with {siteTitle}.'
values={{
siteTitle: instance.title,
}}
/>
</Text>
<Text theme='muted'>
<FormattedMessage
id='onboarding.fediverse.trailer'
defaultMessage='Because it is distributed and anyone can run their own server, the Fediverse is resilient and open. If you choose to join another server or set up your own, you can interact with the same people and continue on the same social graph.'
/>
</Text>
</Stack>
</div>
{account && (
<div className='rounded-lg bg-primary-50 p-4 text-center dark:bg-gray-800'>
<Account account={account} />
</div>
)}
<Text theme='muted'>
<FormattedMessage
id='onboarding.fediverse.its_you'
defaultMessage='This is you! Other people can follow you from other servers by using your full @-handle.'
/>
</Text>
<Text theme='muted'>
<FormattedMessage
id='onboarding.fediverse.other_instances'
defaultMessage='When browsing your timeline, pay attention to the full username after the second @ symbol to know which server a post is from.'
/>
</Text>
</Stack>
</Stack>
<div className='mx-auto pt-10 sm:w-2/3 md:w-1/2'>
<Stack justifyContent='center' space={2}>
<Button
block
theme='primary'
onClick={onNext}
>
<FormattedMessage id='onboarding.fediverse.next' defaultMessage='Next' />
</Button>
</Stack>
</div>
</CardBody>
</Card>
);
};
export default FediverseStep;

Wyświetl plik

@ -1,103 +0,0 @@
import debounce from 'lodash/debounce';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { endOnboarding } from 'soapbox/actions/onboarding';
import { BigCard } from 'soapbox/components/big-card';
import ScrollableList from 'soapbox/components/scrollable-list';
import { Button, Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
import { useAppDispatch } from 'soapbox/hooks';
import { useOnboardingSuggestions } from 'soapbox/queries/suggestions';
const SuggestedAccountsStep = ({ onNext }: { onNext: () => void }) => {
const dispatch = useAppDispatch();
const { data, fetchNextPage, hasNextPage, isFetching } = useOnboardingSuggestions();
const handleLoadMore = debounce(() => {
if (isFetching) {
return null;
}
return fetchNextPage();
}, 300);
const handleComplete = () => {
dispatch(endOnboarding());
};
const renderSuggestions = () => {
if (!data) {
return null;
}
return (
<div className='flex flex-col sm:pb-10 sm:pt-4'>
<ScrollableList
isLoading={isFetching}
scrollKey='suggestions'
onLoadMore={handleLoadMore}
hasMore={hasNextPage}
useWindowScroll={false}
style={{ height: 320 }}
>
{data.map((suggestion) => (
<div key={suggestion.account.id} className='py-2'>
<AccountContainer
id={suggestion.account.id}
showProfileHoverCard={false}
withLinkToProfile={false}
/>
</div>
))}
</ScrollableList>
</div>
);
};
const renderEmpty = () => {
return (
<div className='my-2 rounded-lg bg-primary-50 p-8 text-center dark:bg-gray-800'>
<Text>
<FormattedMessage id='empty_column.follow_recommendations' defaultMessage='Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.' />
</Text>
</div>
);
};
const renderBody = () => {
if (!data || data.length === 0) {
return renderEmpty();
} else {
return renderSuggestions();
}
};
return (
<BigCard
title={<FormattedMessage id='onboarding.suggestions.title' defaultMessage='Suggested accounts' />}
subtitle={<FormattedMessage id='onboarding.suggestions.subtitle' defaultMessage='Here are a few of the most popular accounts you might like.' />}
onClose={handleComplete}
>
{renderBody()}
<Stack>
<Stack justifyContent='center' space={2}>
<Button
block
theme='primary'
onClick={onNext}
>
<FormattedMessage id='onboarding.done' defaultMessage='Done' />
</Button>
<Button block theme='tertiary' type='button' onClick={onNext}>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
</Button>
</Stack>
</Stack>
</BigCard>
);
};
export default SuggestedAccountsStep;