Skip to content

Commit

Permalink
[GEN-1978]: improve UX for end-of-onboarding (#1974)
Browse files Browse the repository at this point in the history
This pull request to
`frontend/webapp/containers/main/destinations/add-destination/index.tsx`
includes changes to improve the user experience by addressing loading
states and preventing double-click issues. The most important changes
include adding a loading spinner, modifying button states, and adjusting
modal behavior.

Loading state improvements:

* Added `FadeLoader` and `CenterThis` to display a loading spinner
during asynchronous operations.
* Introduced `isLoading` state to manage and display loading status,
replacing the previous `sourcesLoading` and `destinationsLoading`
states.
[[1]](diffhunk://#diff-a5ff632e01d3e161b70dce2f959db69fd1893edb484af12b7849810487347001L42-R48)
[[2]](diffhunk://#diff-a5ff632e01d3e161b70dce2f959db69fd1893edb484af12b7849810487347001R58-R59)

Button and modal behavior adjustments:

* Updated button `disabled` property to use `isLoading` state,
preventing user interactions during loading.
[[1]](diffhunk://#diff-a5ff632e01d3e161b70dce2f959db69fd1893edb484af12b7849810487347001L75-R93)
[[2]](diffhunk://#diff-a5ff632e01d3e161b70dce2f959db69fd1893edb484af12b7849810487347001L103-R123)
* Modified modal visibility to depend on `isLoading` state, ensuring it
does not open during loading.
  • Loading branch information
BenElferink authored Dec 11, 2024
1 parent f1962b0 commit 5919acb
Showing 1 changed file with 20 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { useRouter } from 'next/navigation';
import { useDestinationCRUD, useSourceCRUD } from '@/hooks';
import { DestinationModal } from '../destination-modal';
import { ConfiguredDestinationsList } from './configured-destinations-list';
import { Button, NotificationNote, SectionTitle, Text } from '@/reuseable-components';
import { Button, FadeLoader, NotificationNote, SectionTitle, Text } from '@/reuseable-components';
import { CenterThis } from '@/styles';

const ContentWrapper = styled.div`
width: 640px;
Expand Down Expand Up @@ -39,10 +40,12 @@ const StyledAddDestinationButton = styled(Button)`

export function AddDestinationContainer() {
const router = useRouter();
const { createSources, loading: sourcesLoading } = useSourceCRUD();
const { createDestination, loading: destinationsLoading } = useDestinationCRUD();
const { createSources } = useSourceCRUD();
const { createDestination } = useDestinationCRUD();
const { configuredSources, configuredFutureApps, configuredDestinations, resetState } = useAppStore((state) => state);

// we need this state, because "loading" from CRUD hooks is a bit delayed, and allows the user to double-click, as well as see elements render in the UI when they should not be rendered.
const [isLoading, setIsLoading] = useState(false);
const [isModalOpen, setModalOpen] = useState(false);
const handleOpenModal = () => setModalOpen(true);
const handleCloseModal = () => setModalOpen(false);
Expand All @@ -52,6 +55,8 @@ export function AddDestinationContainer() {
};

const clickDone = async () => {
setIsLoading(true);

await createSources(configuredSources, configuredFutureApps);
await Promise.all(configuredDestinations.map(async ({ form }) => await createDestination(form)));

Expand All @@ -60,7 +65,6 @@ export function AddDestinationContainer() {
};

const isSourcesListEmpty = () => !Object.values(configuredSources).some((sources) => !!sources.length);
const isCreating = sourcesLoading || destinationsLoading;

return (
<>
Expand All @@ -72,21 +76,21 @@ export function AddDestinationContainer() {
iconSrc: '/icons/common/arrow-white.svg',
variant: 'secondary',
onClick: clickBack,
disabled: isCreating,
disabled: isLoading,
},
{
label: 'DONE',
variant: 'primary',
onClick: clickDone,
disabled: isCreating,
disabled: isLoading,
},
]}
/>
</HeaderWrapper>
<ContentWrapper>
<SectionTitle title='Configure destinations' description='Select destinations where telemetry data will be sent and configure their settings.' />

{isSourcesListEmpty() && (
{!isLoading && isSourcesListEmpty() && (
<NotificationNoteWrapper>
<NotificationNote
type='warning'
Expand All @@ -100,17 +104,23 @@ export function AddDestinationContainer() {
)}

<AddDestinationButtonWrapper>
<StyledAddDestinationButton variant='secondary' onClick={() => handleOpenModal()}>
<StyledAddDestinationButton variant='secondary' disabled={isLoading} onClick={() => handleOpenModal()}>
<Image src='/icons/common/plus.svg' alt='back' width={16} height={16} />
<Text color={theme.colors.secondary} size={14} decoration='underline' family='secondary'>
ADD DESTINATION
</Text>
</StyledAddDestinationButton>

<DestinationModal isOnboarding isOpen={isModalOpen} onClose={handleCloseModal} />
<DestinationModal isOnboarding isOpen={isModalOpen && !isLoading} onClose={handleCloseModal} />
</AddDestinationButtonWrapper>

<ConfiguredDestinationsList data={configuredDestinations} />
{isLoading ? (
<CenterThis>
<FadeLoader style={{ transform: 'scale(2)', marginTop: '3rem' }} />
</CenterThis>
) : (
<ConfiguredDestinationsList data={configuredDestinations} />
)}
</ContentWrapper>
</>
);
Expand Down

0 comments on commit 5919acb

Please sign in to comment.