From 7ad9b3c1bc4e5985b71989c63fbbab8c2c49916b Mon Sep 17 00:00:00 2001 From: Chris Bongers Date: Tue, 3 Sep 2024 20:50:26 +0200 Subject: [PATCH] feat: add feed error screen --- packages/shared/src/components/Feed.tsx | 9 +++ .../shared/src/components/FeedErrorScreen.tsx | 61 +++++++++++++++++++ packages/shared/src/hooks/useFeed.ts | 8 ++- .../shared/src/hooks/utils/useThemedAsset.ts | 4 ++ packages/shared/src/lib/constants.ts | 1 + packages/shared/src/lib/image.ts | 5 ++ 6 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 packages/shared/src/components/FeedErrorScreen.tsx diff --git a/packages/shared/src/components/Feed.tsx b/packages/shared/src/components/Feed.tsx index f3cc45f602..2f2350817e 100644 --- a/packages/shared/src/components/Feed.tsx +++ b/packages/shared/src/components/Feed.tsx @@ -54,6 +54,10 @@ import { useSearchResultsLayout } from '../hooks/search/useSearchResultsLayout'; import { SearchResultsLayout } from './search/SearchResults/SearchResultsLayout'; import { acquisitionKey } from './cards/AcquisitionForm/common/common'; +const FeedErrorScreen = dynamic( + () => import(/* webpackChunkName: "feedErrorScreen" */ './FeedErrorScreen'), +); + export interface FeedProps extends Pick< UseFeedOptionalParams, @@ -168,6 +172,7 @@ export default function Feed({ emptyFeed, isFetching, isInitialLoading, + isError, } = useFeed( feedQueryKey, pageSize ?? currentSettings.pageSize, @@ -405,6 +410,10 @@ export default function Feed({ const PostModal = PostModalMap[selectedPost?.type]; + if (isError) { + return ; + } + if (emptyScreen && emptyFeed && !isSearchPageLaptop) { return <>{emptyScreen}; } diff --git a/packages/shared/src/components/FeedErrorScreen.tsx b/packages/shared/src/components/FeedErrorScreen.tsx new file mode 100644 index 0000000000..e3e771e7c8 --- /dev/null +++ b/packages/shared/src/components/FeedErrorScreen.tsx @@ -0,0 +1,61 @@ +import React, { ReactElement } from 'react'; +import { PageContainer } from './utilities'; +import { + Typography, + TypographyColor, + TypographyType, +} from './typography/Typography'; +import { Button, ButtonVariant } from './buttons/Button'; +import { useThemedAsset } from '../hooks/utils'; +import { TerminalIcon, TwitterIcon } from './icons'; +import { statusPage, twitter } from '../lib/constants'; +import { anchorDefaultRel } from '../lib/strings'; + +function FeedErrorScreen(): ReactElement { + const { gardrError } = useThemedAsset(); + + return ( + +
+ Production is down (FML) + + Production is down +
+ (FML) +
+ + Our team's on it! Try refreshing the page and cross your fingers, + or send our engineers some good vibes on X (Twitter). + + + +
+
+ ); +} + +export default FeedErrorScreen; diff --git a/packages/shared/src/hooks/useFeed.ts b/packages/shared/src/hooks/useFeed.ts index ddcdc26f96..a0b493d1b1 100644 --- a/packages/shared/src/hooks/useFeed.ts +++ b/packages/shared/src/hooks/useFeed.ts @@ -5,6 +5,7 @@ import { UseInfiniteQueryOptions, useQueryClient, } from '@tanstack/react-query'; +import { ClientError } from 'graphql-request'; import { Ad, FeedData, @@ -22,7 +23,7 @@ import { } from '../lib/query'; import { MarketingCta } from '../components/marketingCta/common'; import { FeedItemType } from '../components/cards/common'; -import { gqlClient } from '../graphql/common'; +import { GARMR_ERROR, gqlClient } from '../graphql/common'; interface FeedItemBase { type: T; @@ -62,6 +63,7 @@ export type FeedReturnType = { isLoading: boolean; isFetching: boolean; isInitialLoading: boolean; + isError: boolean; }; const findIndexOfPostInData = ( @@ -146,6 +148,8 @@ export default function useFeed( }, ); + const clientError = feedQuery?.error as ClientError; + const isAdsQueryEnabled = query && tokenRefreshed && @@ -273,6 +277,8 @@ export default function useFeed( canFetchMore: feedQuery.hasNextPage, emptyFeed: !feedQuery?.data?.pages[0]?.page.edges.length && !feedQuery.isFetching, + isError: + clientError?.response?.errors?.[0]?.extensions?.code === GARMR_ERROR, isLoading: feedQuery.isLoading, isFetching: feedQuery.isFetching, isInitialLoading: feedQuery.isInitialLoading, diff --git a/packages/shared/src/hooks/utils/useThemedAsset.ts b/packages/shared/src/hooks/utils/useThemedAsset.ts index 06ef375fa1..dbc29628f0 100644 --- a/packages/shared/src/hooks/utils/useThemedAsset.ts +++ b/packages/shared/src/hooks/utils/useThemedAsset.ts @@ -10,6 +10,7 @@ interface UseAsset { themeColor: string; githubShortcut: string; slackIntegrationHeader: string; + gardrError: string; } export const useIsLightTheme = (): boolean => { @@ -45,5 +46,8 @@ export const useThemedAsset = (): UseAsset => { slackIntegrationHeader: isLight ? cloudinary.integrations.slack.header.light : cloudinary.integrations.slack.header.dark, + gardrError: isLight + ? cloudinary.generic.error.light + : cloudinary.generic.error.dark, }; }; diff --git a/packages/shared/src/lib/constants.ts b/packages/shared/src/lib/constants.ts index 84647c9c72..61417dac69 100644 --- a/packages/shared/src/lib/constants.ts +++ b/packages/shared/src/lib/constants.ts @@ -39,6 +39,7 @@ export const squadsPublicGuide = 'https://r.daily.dev/public-squads-guide'; export const searchFeedback = 'https://r.daily.dev/search-feedback'; export const searchDocs = 'https://r.daily.dev/search-docs'; export const slackIntegration = 'https://r.daily.dev/slack'; +export const statusPage = 'https://r.daily.dev/status'; export const isDevelopment = process.env.NODE_ENV === 'development'; export const isProduction = process.env.NODE_ENV === 'production'; export const isTesting = diff --git a/packages/shared/src/lib/image.ts b/packages/shared/src/lib/image.ts index e2c3aff12f..880b8cda31 100644 --- a/packages/shared/src/lib/image.ts +++ b/packages/shared/src/lib/image.ts @@ -161,6 +161,11 @@ export const cloudinary = { 'https://daily-now-res.cloudinary.com/image/upload/s--t81_4qLS--/f_auto/v1708330060/404-lightmode_eweviu', dark: 'https://daily-now-res.cloudinary.com/image/upload/s--Rxdm7vdJ--/f_auto/v1708328512/404_z4xiwg', }, + error: { + light: + 'https://daily-now-res.cloudinary.com/image/upload/v1725365692/lightversion_dmnj1s.gif', + dark: 'https://daily-now-res.cloudinary.com/image/upload/v1725365692/darkversion_bfrze7.gif', + }, }, streak: { splash: