All files / apps/host/src/components/RequestList index.tsx

100% Statements 19/19
78.57% Branches 22/28
100% Functions 8/8
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                                              4x 9x     9x                     9x         9x   9x 2x 5x       9x 2x     9x 1x     1x               9x   9x 12x       9x                                   12x                                                 4x                    
import React, { memo, useCallback, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
 
import { FlashList } from '@shopify/flash-list';
import { useQueryClient } from '@tanstack/react-query';
 
import { textStyles } from '@repo/ui/themes/typography';
 
import RequestCard from '@/components/RequestCard';
import { RequestSkeleton } from '@/components/RequestListSkeleton';
 
import { useGetMyRequests, useGetRequests } from '@/hooks/useRequest';
 
import { QUERY_KEYS } from '@/constants/apis';
 
import { RequestCategory, RequestStatus } from '@/types/request';
 
interface Props {
  status?: RequestStatus;
  isMyRequest?: boolean;
  onPressItem: (id: string, category: RequestCategory) => void;
}
 
const RequestList = ({ status, isMyRequest = false, onPressItem }: Props) => {
  const queryClient = useQueryClient();
 
  const { data, isLoading, error, fetchNextPage, isRefetching, isFetchingNextPage } =
    useGetRequests({
      status,
      disabled: isMyRequest,
    });
 
  const {
    data: myRequestData,
    isLoading: isMyRequestLoading,
    error: myRequestError,
    fetchNextPage: myRequestFetchNextPage,
    isRefetching: myRequestIsReFetching,
  } = useGetMyRequests({
    status,
    disabled: !isMyRequest,
  });
 
  const requests = useMemo(
    () =>
      (isMyRequest
        ? myRequestData?.pages.flatMap(page => page.data.items)
        : data?.pages.flatMap(page => page.data.items)) ?? [],
    [data, myRequestData, isMyRequest],
  );
 
  const handleLoadMore = useCallback(() => {
    isMyRequest ? myRequestFetchNextPage() : fetchNextPage();
  }, [fetchNextPage, isMyRequest, myRequestFetchNextPage]);
 
  const handleRefresh = useCallback(() => {
    queryClient.refetchQueries({
      queryKey: [isMyRequest ? QUERY_KEYS.MY_REQUESTS : QUERY_KEYS.LIST_REQUESTS],
    });
    status &&
      queryClient.refetchQueries({
        queryKey: isMyRequest
          ? [QUERY_KEYS.MY_REQUESTS, status]
          : [QUERY_KEYS.LIST_REQUESTS, status],
      });
  }, [isMyRequest, queryClient, status]);
 
  const isLoadingData = isLoading || isRefetching || isMyRequestLoading || myRequestIsReFetching;
 
  const renderItem = useCallback(
    ({ item }: { item: any }) => <RequestCard {...item} onPress={onPressItem} />,
    [onPressItem],
  );
 
  return (
    <View style={styles.container}>
      {error && (
        <Text style={textStyles.content.regular} accessibilityRole="alert">
          {error.message}
        </Text>
      )}
      {myRequestError && (
        <Text style={textStyles.content.regular} accessibilityRole="alert">
          {myRequestError.message}
        </Text>
      )}
      {isLoadingData ? (
        <RequestSkeleton />
      ) : (
        <FlashList
          onRefresh={handleRefresh}
          data={requests}
          keyExtractor={item => item.id}
          renderItem={renderItem}
          showsVerticalScrollIndicator={false}
          contentContainerStyle={styles.contentContainer}
          onEndReached={handleLoadMore}
          onEndReachedThreshold={0.5}
          accessibilityRole="list"
          accessibilityLabel="Requests"
          {...(isFetchingNextPage && {
            ListFooterComponent: <RequestSkeleton />,
          })}
          {...(requests.length === 0 &&
            !isLoadingData && {
              ListEmptyComponent: (
                <Text className="text-center text-xl" style={textStyles.content.regular}>
                  No request found
                </Text>
              ),
            })}
        />
      )}
    </View>
  );
};
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  contentContainer: {
    paddingBottom: 20,
  },
});
 
export default memo(RequestList);