Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

23- Pesquisa - Funcionalidade de Ponta a Ponta com Teste de Integração #19

Merged
merged 15 commits into from
Nov 20, 2023
Merged
8 changes: 2 additions & 6 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import React from 'react';

// import {ToastProvider} from '@services';
import {
AuthCredentialsProvider,
initializeStorage,
MMKVStorage,
} from '@services';
import {ThemeProvider} from '@shopify/restyle';
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
import {SafeAreaProvider} from 'react-native-safe-area-context';

import {Toast} from '@components';

import {Router} from './src/routes/Routes';
import {AuthCredentialsProvider} from './src/services/authCredentials/Providers/AuthCredentialsProvider';
import {initializeStorage, MMKVStorage} from './src/services/storage';
import {theme} from './src/theme/theme';

initializeStorage(MMKVStorage);
Expand Down
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const config: Config = {
],
coveragePathIgnorePatterns: ['/node_modules/', 'index'],
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|react-native-safe-area-context)/)',
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|react-native-safe-area-context|@react-navigation)/)',
],
};

Expand Down
15 changes: 13 additions & 2 deletions src/api/apiAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {MetaDataPage} from '@types';
import {MetaDataPage, Page} from '@types';

import {MetaDataPageAPI} from './apiTypes';
import {MetaDataPageAPI, PageAPI} from './apiTypes';

function toMetaDataPage(meta: MetaDataPageAPI): MetaDataPage {
return {
Expand All @@ -14,6 +14,17 @@ function toMetaDataPage(meta: MetaDataPageAPI): MetaDataPage {
};
}

function toPageModel<ApiType, ModelType>(
page: PageAPI<ApiType>,
adapterToModel: (api: ApiType) => ModelType,
): Page<ModelType> {
return {
meta: toMetaDataPage(page.meta),
data: page.data.map(adapterToModel),
};
}

export const apiAdapter = {
toMetaDataPage,
toPageModel,
};
14 changes: 11 additions & 3 deletions src/components/Box/Box.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
TouchableOpacity,
TouchableOpacityProps as RNTouchableOpacityProps,
PressableProps,
} from 'react-native';

import {
Expand All @@ -23,12 +24,13 @@ import {Theme} from '@theme';
export const Box = createBox<Theme>();
export type BoxProps = React.ComponentProps<typeof Box>;

export type TouchableOpacityBoxProps = BackgroundColorProps<Theme> &
type RestyleTypes = BackgroundColorProps<Theme> &
SpacingProps<Theme> &
LayoutProps<Theme> &
BorderProps<Theme> &
SpacingShorthandProps<Theme> &
RNTouchableOpacityProps;
SpacingShorthandProps<Theme>;

export type TouchableOpacityBoxProps = RNTouchableOpacityProps & RestyleTypes;

export const TouchableOpacityBox = createRestyleComponent<
TouchableOpacityBoxProps,
Expand All @@ -37,3 +39,9 @@ export const TouchableOpacityBox = createRestyleComponent<
[backgroundColor, spacing, spacingShorthand, layout, border],
TouchableOpacity,
);

export type PressableBoxProps = PressableProps & RestyleTypes;
export const PressableBox = createRestyleComponent<PressableBoxProps, Theme>(
[backgroundColor, spacing, spacingShorthand, layout, border],
TouchableOpacity,
);
11 changes: 8 additions & 3 deletions src/components/PostItem/PostItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import React from 'react';

import {Post} from '@domain';

import {Box} from '@components';
import {Box, ProfileUser} from '@components';

import {PostActions} from './components/PostActions';
import {PostBottom} from './components/PostBottom';
import {PostHeader} from './components/PostHeader';
import {PostImage} from './components/PostImage';

interface Props {
Expand All @@ -15,7 +14,13 @@ interface Props {
export function PostItem({post}: Props) {
return (
<Box paddingHorizontal="s24" marginBottom="s24">
<PostHeader author={post.author} />
<ProfileUser
user={{
id: post.author.id,
username: post.author.userName,
profileUrl: post.author.profileURL,
}}
/>
<PostImage imageURL={post.imageURL} />
<PostActions
commentCount={post.commentCount}
Expand Down
27 changes: 0 additions & 27 deletions src/components/PostItem/components/PostHeader.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/ProfileAvatar/ProfileAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import {Image} from 'react-native';

interface ProfileAvatarProps {
export interface ProfileAvatarProps {
imageURL: string;
/** @default 32 */
size?: number;
Expand Down
54 changes: 54 additions & 0 deletions src/components/ProfileUser/ProfileUser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import {GestureResponderEvent} from 'react-native';

import {User} from '@domain';
import {useNavigation} from '@react-navigation/native';

import {
Text,
ProfileAvatar,
PressableBox,
PressableBoxProps,
ProfileAvatarProps,
Box,
} from '@components';

type ProfileUserProps = {
user: Pick<User, 'username' | 'profileUrl' | 'id'>;
avatarProps?: Omit<Partial<ProfileAvatarProps>, 'imageURL'>;
RightComponent?: React.ReactElement;
} & PressableBoxProps;
export function ProfileUser({
user,
avatarProps,
RightComponent,
onPress,
...pressableBoxProps
}: ProfileUserProps) {
const navigation = useNavigation();

function handleOnPress(event: GestureResponderEvent) {
if (onPress) {
onPress(event);
}
navigation.navigate('ProfileScreen', {userId: user.id});
}

return (
<PressableBox
flexDirection="row"
alignItems="center"
justifyContent="space-between"
mb="s16"
onPress={handleOnPress}
{...pressableBoxProps}>
<Box flexDirection="row" alignItems="center">
<ProfileAvatar {...avatarProps} imageURL={user.profileUrl} />
<Text ml="s12" semiBold preset="paragraphMedium">
{user.username}
</Text>
</Box>
{RightComponent}
</PressableBox>
);
}
8 changes: 7 additions & 1 deletion src/components/Screen/Screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

export interface ScreenProps extends BoxProps {
children: React.ReactNode;
HeaderComponent?: React.ReactNode;
canGoBack?: boolean;
scrollable?: boolean;
title?: string;
Expand All @@ -19,6 +20,7 @@
scrollable = false,
style,
title,
HeaderComponent,
...boxProps
}: ScreenProps) {
const {bottom, top} = useAppSafeArea();
Expand All @@ -27,14 +29,18 @@
const Container = scrollable ? ScrollViewContainer : ViewContainer;
return (
<KeyboardAvoidingView
style={{flex: 1}}

Check warning on line 32 in src/components/Screen/Screen.tsx

View workflow job for this annotation

GitHub Actions / pull-request-checks

Inline style: { flex: 1 }
behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
<Container backgroundColor={colors.background}>
<Box
paddingHorizontal="s24"
style={[{paddingTop: top, paddingBottom: bottom}, style]}
{...boxProps}>
<ScreenHeader canGoBack={canGoBack} title={title} />
<ScreenHeader
HeaderComponent={HeaderComponent}
canGoBack={canGoBack}
title={title}
/>
{children}
</Box>
</Container>
Expand Down
11 changes: 8 additions & 3 deletions src/components/Screen/components/ScreenHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import {Box, Icon, Text, TouchableOpacityBox} from '@components';
import {ScreenProps} from '../Screen';

const ICON_SIZE = 20;
type Props = Pick<ScreenProps, 'title' | 'canGoBack'>;
export function ScreenHeader({canGoBack, title}: Props) {
type Props = Pick<ScreenProps, 'title' | 'canGoBack' | 'HeaderComponent'>;
export function ScreenHeader({canGoBack, title, HeaderComponent}: Props) {
const navigation = useNavigation();

const showBackLabel = !title && !HeaderComponent;

return (
<Box
flexDirection="row"
Expand All @@ -19,17 +21,20 @@ export function ScreenHeader({canGoBack, title}: Props) {
justifyContent="space-between">
{canGoBack && (
<TouchableOpacityBox
testID="screen-back-button"
flexDirection="row"
alignItems="center"
mr="s10"
onPress={navigation.goBack}>
<Icon size={ICON_SIZE} name="arrowLeft" color="primary" />
{!title && (
{showBackLabel && (
<Text preset="paragraphMedium" semiBold ml="s8">
Voltar
</Text>
)}
</TouchableOpacityBox>
)}
{HeaderComponent}
{title && <Text preset="headingSmall">{title}</Text>}
{title && <Box backgroundColor="carrotSecondary" width={ICON_SIZE} />}
</Box>
Expand Down
19 changes: 14 additions & 5 deletions src/components/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import {Box, BoxProps} from '../Box/Box';
import {$fontFamily, $fontSizes, Text} from '../Text/Text';

export interface TextInputProps extends RNTextInputProps {
label: string;
label?: string;
errorMessage?: string;
RightComponent?: React.ReactElement;
LeftComponent?: React.ReactElement;
boxProps?: BoxProps;
}
export function TextInput({
label,
errorMessage,
RightComponent,
LeftComponent,
boxProps,
...rnTextInputProps
}: TextInputProps) {
Expand All @@ -39,12 +41,19 @@ export function TextInput({
inputRef.current?.focus();
}
return (
<Box {...boxProps}>
<Box flexGrow={1} flexShrink={1} {...boxProps}>
<Pressable onPress={focusInput}>
<Text preset="paragraphMedium" marginBottom="s4">
{label}
</Text>
{label && (
<Text preset="paragraphMedium" marginBottom="s4">
{label}
</Text>
)}
<Box {...$textInputContainer}>
{LeftComponent && (
<Box justifyContent="center" mr="s16">
{LeftComponent}
</Box>
)}
<RNTextInput
autoCapitalize="none"
ref={inputRef}
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './PostItem/PostItem';
export * from './ProfileAvatar/ProfileAvatar';
export * from './TextMessage/TextMessage';
export * from './Toast/Toast';
export * from './ProfileUser/ProfileUser';
8 changes: 6 additions & 2 deletions src/domain/Auth/useCases/useAuthSignOut.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import {useAuthCredentials} from '@services';
import {useAuthCredentials, useSearchHistoryService} from '@services';
import {useMutation} from '@tanstack/react-query';

import {authService} from '../authService';

export function useAuthSignOut() {
const {removeCredentials} = useAuthCredentials();
const {clearUserList} = useSearchHistoryService();
const mutation = useMutation<string, unknown, void>({
mutationFn: authService.signOut,
retry: false,
onSuccess: removeCredentials,
onSettled: () => {
removeCredentials();
clearUserList();
},
});

return {
Expand Down
5 changes: 1 addition & 4 deletions src/domain/Post/postService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import {Post} from './postTypes';
async function getList(page: number): Promise<Page<Post>> {
const postPageAPI = await postApi.getList({page, per_page: 10});

return {
data: postPageAPI.data.map(postAdapter.toPost),
meta: apiAdapter.toMetaDataPage(postPageAPI.meta),
};
return apiAdapter.toPageModel(postPageAPI, postAdapter.toPost);
}

export const postService = {
Expand Down
8 changes: 4 additions & 4 deletions src/domain/PostComment/postCommentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ async function getList(
per_page: PER_PAGE,
});

return {
data: postCommentPageAPI.data.map(postCommentAdapter.toPostComment),
meta: apiAdapter.toMetaDataPage(postCommentPageAPI.meta),
};
return apiAdapter.toPageModel(
postCommentPageAPI,
postCommentAdapter.toPostComment,
);
}

async function create(postId: number, message: string): Promise<PostComment> {
Expand Down
2 changes: 2 additions & 0 deletions src/domain/User/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './userTypes';
export * from './userService';
export * from './userAdapter';
export {USER_PATH} from './userApi';
export * from './useCases/useUserGetById';
export * from './useCases/useUserSearch';
14 changes: 14 additions & 0 deletions src/domain/User/useCases/useUserSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {QueryKeys, usePaginatedList} from '@infra';

import {userService} from '../userService';

export function useUserSearch(search: string) {
return usePaginatedList(
[QueryKeys.UserList, search],
() => userService.searchUser(search),
{
enabled: search.length > 0,
staleTime: 30000,
},
);
}
Loading
Loading