sforkowany z mirror/soapbox
				
			Improve error handling for Groups Discover page
							rodzic
							
								
									e7b3af5260
								
							
						
					
					
						commit
						287fda6d6c
					
				| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
import React, { useState } from 'react';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
 | 
			
		||||
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
 | 
			
		||||
| 
						 | 
				
			
			@ -7,46 +8,59 @@ import { usePopularGroups } from 'soapbox/queries/groups';
 | 
			
		|||
import Group from './group';
 | 
			
		||||
 | 
			
		||||
const PopularGroups = () => {
 | 
			
		||||
  const { groups, isFetching } = usePopularGroups();
 | 
			
		||||
  const { groups, isFetching, isFetched, isError } = usePopularGroups();
 | 
			
		||||
  const isEmpty = (isFetched && groups.length === 0) || isError;
 | 
			
		||||
 | 
			
		||||
  const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Stack space={4}>
 | 
			
		||||
      <Text size='xl' weight='bold'>
 | 
			
		||||
        Popular Groups
 | 
			
		||||
        <FormattedMessage
 | 
			
		||||
          id='groups.discover.popular.title'
 | 
			
		||||
          defaultMessage='Popular Groups'
 | 
			
		||||
        />
 | 
			
		||||
      </Text>
 | 
			
		||||
 | 
			
		||||
      <Carousel
 | 
			
		||||
        itemWidth={250}
 | 
			
		||||
        itemCount={groups.length}
 | 
			
		||||
        controlsHeight={groupCover?.clientHeight}
 | 
			
		||||
      >
 | 
			
		||||
        {({ width }: { width: number }) => (
 | 
			
		||||
          <>
 | 
			
		||||
            {isFetching ? (
 | 
			
		||||
              new Array(20).fill(0).map((_, idx) => (
 | 
			
		||||
                <div
 | 
			
		||||
                  className='relative flex shrink-0 flex-col space-y-2 px-0.5'
 | 
			
		||||
                  style={{ width: width || 'auto' }}
 | 
			
		||||
                  key={idx}
 | 
			
		||||
                >
 | 
			
		||||
                  <PlaceholderGroupDiscover />
 | 
			
		||||
                </div>
 | 
			
		||||
              ))
 | 
			
		||||
            ) : (
 | 
			
		||||
              groups.map((group) => (
 | 
			
		||||
                <Group
 | 
			
		||||
                  key={group.id}
 | 
			
		||||
                  group={group}
 | 
			
		||||
                  width={width}
 | 
			
		||||
                  ref={setGroupCover}
 | 
			
		||||
                />
 | 
			
		||||
              ))
 | 
			
		||||
            )}
 | 
			
		||||
          </>
 | 
			
		||||
        )}
 | 
			
		||||
      </Carousel>
 | 
			
		||||
      {isEmpty ? (
 | 
			
		||||
        <Text theme='muted'>
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.popular.empty'
 | 
			
		||||
            defaultMessage='Unable to fetch popular groups at this time. Please check back later.'
 | 
			
		||||
          />
 | 
			
		||||
        </Text>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <Carousel
 | 
			
		||||
          itemWidth={250}
 | 
			
		||||
          itemCount={groups.length}
 | 
			
		||||
          controlsHeight={groupCover?.clientHeight}
 | 
			
		||||
        >
 | 
			
		||||
          {({ width }: { width: number }) => (
 | 
			
		||||
            <>
 | 
			
		||||
              {isFetching ? (
 | 
			
		||||
                new Array(20).fill(0).map((_, idx) => (
 | 
			
		||||
                  <div
 | 
			
		||||
                    className='relative flex shrink-0 flex-col space-y-2 px-0.5'
 | 
			
		||||
                    style={{ width: width || 'auto' }}
 | 
			
		||||
                    key={idx}
 | 
			
		||||
                  >
 | 
			
		||||
                    <PlaceholderGroupDiscover />
 | 
			
		||||
                  </div>
 | 
			
		||||
                ))
 | 
			
		||||
              ) : (
 | 
			
		||||
                groups.map((group) => (
 | 
			
		||||
                  <Group
 | 
			
		||||
                    key={group.id}
 | 
			
		||||
                    group={group}
 | 
			
		||||
                    width={width}
 | 
			
		||||
                    ref={setGroupCover}
 | 
			
		||||
                  />
 | 
			
		||||
                ))
 | 
			
		||||
              )}
 | 
			
		||||
            </>
 | 
			
		||||
          )}
 | 
			
		||||
        </Carousel>
 | 
			
		||||
      )}
 | 
			
		||||
    </Stack>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import { Stack, Text } from 'soapbox/components/ui';
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  title: React.ReactNode | string
 | 
			
		||||
  subtitle: React.ReactNode | string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default ({ title, subtitle }: Props) => (
 | 
			
		||||
  <Stack space={2} className='px-4 py-2' data-testid='no-results'>
 | 
			
		||||
    <Text weight='bold' size='lg'>
 | 
			
		||||
      {title}
 | 
			
		||||
    </Text>
 | 
			
		||||
 | 
			
		||||
    <Text theme='muted'>
 | 
			
		||||
      {subtitle}
 | 
			
		||||
    </Text>
 | 
			
		||||
  </Stack>
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +0,0 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import { Stack, Text } from 'soapbox/components/ui';
 | 
			
		||||
 | 
			
		||||
export default () => (
 | 
			
		||||
  <Stack space={2} className='px-4 py-2' data-testid='no-results'>
 | 
			
		||||
    <Text weight='bold' size='lg'>
 | 
			
		||||
      <FormattedMessage
 | 
			
		||||
        id='groups.discover.search.no_results.title'
 | 
			
		||||
        defaultMessage='No matches found'
 | 
			
		||||
      />
 | 
			
		||||
    </Text>
 | 
			
		||||
 | 
			
		||||
    <Text theme='muted'>
 | 
			
		||||
      <FormattedMessage
 | 
			
		||||
        id='groups.discover.search.no_results.subtitle'
 | 
			
		||||
        defaultMessage='Try searching for another group.'
 | 
			
		||||
      />
 | 
			
		||||
    </Text>
 | 
			
		||||
  </Stack>
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
import React, { useEffect } from 'react';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import { Stack } from 'soapbox/components/ui';
 | 
			
		||||
import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +7,7 @@ import { useDebounce, useOwnAccount } from 'soapbox/hooks';
 | 
			
		|||
import { useGroupSearch } from 'soapbox/queries/groups/search';
 | 
			
		||||
import { saveGroupSearch } from 'soapbox/utils/groups';
 | 
			
		||||
 | 
			
		||||
import NoResultsBlankslate from './no-results-blankslate';
 | 
			
		||||
import Blankslate from './blankslate';
 | 
			
		||||
import RecentSearches from './recent-searches';
 | 
			
		||||
import Results from './results';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +26,7 @@ export default (props: Props) => {
 | 
			
		|||
  const debouncedValueToSave = debounce(searchValue as string, 1000);
 | 
			
		||||
 | 
			
		||||
  const groupSearchResult = useGroupSearch(debouncedValue);
 | 
			
		||||
  const { groups, isFetching, isFetched } = groupSearchResult;
 | 
			
		||||
  const { groups, isFetching, isFetched, isError } = groupSearchResult;
 | 
			
		||||
 | 
			
		||||
  const hasSearchResults = isFetched && groups.length > 0;
 | 
			
		||||
  const hasNoSearchResults = isFetched && groups.length === 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,8 +47,42 @@ export default (props: Props) => {
 | 
			
		|||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (isError) {
 | 
			
		||||
    return (
 | 
			
		||||
      <Blankslate
 | 
			
		||||
        title={
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.search.error.title'
 | 
			
		||||
            defaultMessage='An error occurred'
 | 
			
		||||
          />
 | 
			
		||||
        }
 | 
			
		||||
        subtitle={
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.search.error.subtitle'
 | 
			
		||||
            defaultMessage='Please try again later.'
 | 
			
		||||
          />
 | 
			
		||||
        }
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (hasNoSearchResults) {
 | 
			
		||||
    return <NoResultsBlankslate />;
 | 
			
		||||
    return (
 | 
			
		||||
      <Blankslate
 | 
			
		||||
        title={
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.search.no_results.title'
 | 
			
		||||
            defaultMessage='No matches found'
 | 
			
		||||
          />
 | 
			
		||||
        }
 | 
			
		||||
        subtitle={
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.search.no_results.subtitle'
 | 
			
		||||
            defaultMessage='Try searching for another group.'
 | 
			
		||||
          />
 | 
			
		||||
        }
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (hasSearchResults) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
import React, { useState } from 'react';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
 | 
			
		||||
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
 | 
			
		||||
| 
						 | 
				
			
			@ -7,46 +8,59 @@ import { useSuggestedGroups } from 'soapbox/queries/groups';
 | 
			
		|||
import Group from './group';
 | 
			
		||||
 | 
			
		||||
const SuggestedGroups = () => {
 | 
			
		||||
  const { groups, isFetching } = useSuggestedGroups();
 | 
			
		||||
  const { groups, isFetching, isFetched, isError } = useSuggestedGroups();
 | 
			
		||||
  const isEmpty = (isFetched && groups.length === 0) || isError;
 | 
			
		||||
 | 
			
		||||
  const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Stack space={4}>
 | 
			
		||||
      <Text size='xl' weight='bold'>
 | 
			
		||||
        Suggested For You
 | 
			
		||||
        <FormattedMessage
 | 
			
		||||
          id='groups.discover.suggested.title'
 | 
			
		||||
          defaultMessage='Suggested For You'
 | 
			
		||||
        />
 | 
			
		||||
      </Text>
 | 
			
		||||
 | 
			
		||||
      <Carousel
 | 
			
		||||
        itemWidth={250}
 | 
			
		||||
        itemCount={groups.length}
 | 
			
		||||
        controlsHeight={groupCover?.clientHeight}
 | 
			
		||||
      >
 | 
			
		||||
        {({ width }: { width: number }) => (
 | 
			
		||||
          <>
 | 
			
		||||
            {isFetching ? (
 | 
			
		||||
              new Array(20).fill(0).map((_, idx) => (
 | 
			
		||||
                <div
 | 
			
		||||
                  className='relative flex shrink-0 flex-col space-y-2 px-0.5'
 | 
			
		||||
                  style={{ width: width || 'auto' }}
 | 
			
		||||
                  key={idx}
 | 
			
		||||
                >
 | 
			
		||||
                  <PlaceholderGroupDiscover />
 | 
			
		||||
                </div>
 | 
			
		||||
              ))
 | 
			
		||||
            ) : (
 | 
			
		||||
              groups.map((group) => (
 | 
			
		||||
                <Group
 | 
			
		||||
                  key={group.id}
 | 
			
		||||
                  group={group}
 | 
			
		||||
                  width={width}
 | 
			
		||||
                  ref={setGroupCover}
 | 
			
		||||
                />
 | 
			
		||||
              ))
 | 
			
		||||
            )}
 | 
			
		||||
          </>
 | 
			
		||||
        )}
 | 
			
		||||
      </Carousel>
 | 
			
		||||
      {isEmpty ? (
 | 
			
		||||
        <Text theme='muted'>
 | 
			
		||||
          <FormattedMessage
 | 
			
		||||
            id='groups.discover.suggested.empty'
 | 
			
		||||
            defaultMessage='Unable to fetch suggested groups at this time. Please check back later.'
 | 
			
		||||
          />
 | 
			
		||||
        </Text>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <Carousel
 | 
			
		||||
          itemWidth={250}
 | 
			
		||||
          itemCount={groups.length}
 | 
			
		||||
          controlsHeight={groupCover?.clientHeight}
 | 
			
		||||
        >
 | 
			
		||||
          {({ width }: { width: number }) => (
 | 
			
		||||
            <>
 | 
			
		||||
              {isFetching ? (
 | 
			
		||||
                new Array(20).fill(0).map((_, idx) => (
 | 
			
		||||
                  <div
 | 
			
		||||
                    className='relative flex shrink-0 flex-col space-y-2 px-0.5'
 | 
			
		||||
                    style={{ width: width || 'auto' }}
 | 
			
		||||
                    key={idx}
 | 
			
		||||
                  >
 | 
			
		||||
                    <PlaceholderGroupDiscover />
 | 
			
		||||
                  </div>
 | 
			
		||||
                ))
 | 
			
		||||
              ) : (
 | 
			
		||||
                groups.map((group) => (
 | 
			
		||||
                  <Group
 | 
			
		||||
                    key={group.id}
 | 
			
		||||
                    group={group}
 | 
			
		||||
                    width={width}
 | 
			
		||||
                    ref={setGroupCover}
 | 
			
		||||
                  />
 | 
			
		||||
                ))
 | 
			
		||||
              )}
 | 
			
		||||
            </>
 | 
			
		||||
          )}
 | 
			
		||||
        </Carousel>
 | 
			
		||||
      )}
 | 
			
		||||
    </Stack>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -803,6 +803,8 @@
 | 
			
		|||
  "group.user_subheading": "Users",
 | 
			
		||||
  "groups.discover.search.no_results.subtitle": "Try searching for another group.",
 | 
			
		||||
  "groups.discover.search.no_results.title": "No matches found",
 | 
			
		||||
  "groups.discover.search.error.subtitle": "Please try again later.",
 | 
			
		||||
  "groups.discover.search.error.title": "An error occurred",
 | 
			
		||||
  "groups.discover.search.placeholder": "Search",
 | 
			
		||||
  "groups.discover.search.recent_searches.blankslate.subtitle": "Search group names, topics or keywords",
 | 
			
		||||
  "groups.discover.search.recent_searches.blankslate.title": "No recent searches",
 | 
			
		||||
| 
						 | 
				
			
			@ -810,6 +812,10 @@
 | 
			
		|||
  "groups.discover.search.recent_searches.title": "Recent searches",
 | 
			
		||||
  "groups.discover.search.results.groups": "Groups",
 | 
			
		||||
  "groups.discover.search.results.member_count": "{members, plural, one {member} other {members}}",
 | 
			
		||||
  "groups.discover.popular.title": "Popular Groups",
 | 
			
		||||
  "groups.discover.popular.empty": "Unable to fetch popular groups at this time. Please check back later.",
 | 
			
		||||
  "groups.discover.suggested.title": "Suggested For You",
 | 
			
		||||
  "groups.discover.suggested.empty": "Unable to fetch suggested groups at this time. Please check back later.",
 | 
			
		||||
  "groups.empty.subtitle": "Start discovering groups to join or create your own.",
 | 
			
		||||
  "groups.empty.title": "No Groups yet",
 | 
			
		||||
  "hashtag.column_header.tag_mode.all": "and {additional}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue