Skip to content

Commit

Permalink
fix(app): improve loading experience during navigation (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
danadajian authored Jun 8, 2023
1 parent 080245e commit 136b127
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 34 deletions.
19 changes: 17 additions & 2 deletions app/frontend/components/loader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import * as React from 'react';
import Island from '../resources/Island.svg';

export const Loader = () => {
export const LoaderViews = {
FULL_SCREEN: 'FULL_SCREEN',
PARTIAL: 'PARTIAL'
} as const;
type View = keyof typeof LoaderViews;

export const Loader = ({ view }: { view: View }) => {
return (
<div className="flex min-h-screen items-center justify-center">
<div className={`flex items-center justify-center ${getViewClass(view)}`}>
<img className="w-1/6 animate-pulse" src={Island} alt="comparadise-loader" />
</div>
);
};

const getViewClass = (view: View) => {
switch (view) {
case LoaderViews.FULL_SCREEN:
return 'min-h-screen';
case LoaderViews.PARTIAL:
return 'mt-48';
}
};
59 changes: 37 additions & 22 deletions app/frontend/components/main-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { useEffect } from 'react';
import { LandingPage } from './landing-page';
import { Error } from './error';
import { Loader } from './loader';
import { Loader, LoaderViews } from './loader';
import { ViewToggle, ViewType } from './view-toggle';
import { UpdateImagesButton } from './update-images-button';
import { SideBySideImageView, SingleImageView } from './image-views';
Expand All @@ -22,9 +22,14 @@ export const MainPage = () => {
return <LandingPage />;
}

const { data, fetchNextPage, fetchPreviousPage, isLoading, error } = trpc.fetchCurrentPage.useInfiniteQuery(
const { isLoading, data, fetchNextPage, fetchPreviousPage, isFetching, error } = trpc.fetchCurrentPage.useInfiniteQuery(
{ hash, bucket },
{ getNextPageParam: currentPage => currentPage.nextPage, initialCursor: 1 }
{
initialCursor: 1,
getNextPageParam: currentPage => currentPage.nextPage,
keepPreviousData: true,
refetchOnWindowFocus: false
}
);

const currentPage = data?.pages[specIndex];
Expand All @@ -41,28 +46,34 @@ export const MainPage = () => {
return <Error error={error} />;
}

if (isLoading || !currentPage) {
return <Loader />;
if (isLoading) {
return <Loader view={LoaderViews.FULL_SCREEN} />;
}

const onClickBackArrow = async () => {
await fetchPreviousPage();
setSpecIndex(specIndex - 1);
fetchPreviousPage();
};

const onClickForwardArrow = async () => {
await fetchNextPage();
setSpecIndex(specIndex + 1);
fetchNextPage();
};

const imageView =
viewType === ViewType.SIDE_BY_SIDE ? (
<SideBySideImageView images={currentPage.images} />
) : (
<SingleImageView images={currentPage.images} selectedImageIndex={singleImageViewIndex} onSelectImage={setSingleImageViewIndex} />
);
const getImageBody = () => {
if (isFetching || !currentPage) {
return <Loader view={LoaderViews.PARTIAL} />;
}
const imageView =
viewType === ViewType.SIDE_BY_SIDE ? (
<SideBySideImageView images={currentPage.images} />
) : (
<SingleImageView images={currentPage.images} selectedImageIndex={singleImageViewIndex} onSelectImage={setSingleImageViewIndex} />
);
return <div className="mt-8">{imageView}</div>;
};

const nextPageExists = Boolean(currentPage.nextPage);
const nextPageExists = Boolean(currentPage?.nextPage);

return (
<>
Expand All @@ -71,19 +82,23 @@ export const MainPage = () => {
<button disabled={specIndex <= 0} onClick={onClickBackArrow} aria-label="back-arrow">
<ArrowBackIcon disabled={specIndex <= 0} />
</button>
<h1 className="text-center text-4xl font-medium">{currentPage.title}</h1>
<h1 className="text-center text-4xl font-medium">{currentPage?.title}</h1>
<button disabled={!nextPageExists} onClick={onClickForwardArrow} aria-label="forward-arrow">
<ArrowForwardIcon disabled={!nextPageExists} />
</button>
</div>
<div className="mt-8">
<UpdateImagesButton />
</div>
<div className="mt-5">
<ViewToggle selectedView={viewType} onSelectView={setViewType} />
</div>
{!isFetching && (
<>
<div className="mt-8">
<UpdateImagesButton />
</div>
<div className="mt-5">
<ViewToggle selectedView={viewType} onSelectView={setViewType} />
</div>
</>
)}
</div>
<div className="mt-8">{imageView}</div>
{getImageBody()}
</>
);
};
Expand Down
14 changes: 4 additions & 10 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@
"extensions": "ts"
}
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
"nx": {
"implicitDependencies": [
"backend",
"frontend"
]
}
}

0 comments on commit 136b127

Please sign in to comment.