Skip to content

Commit

Permalink
Merge pull request #190 from mohammadkhizerkhan/feature/get-user-api-…
Browse files Browse the repository at this point in the history
…integration

Feature/get user api integration
  • Loading branch information
shreya-mishra authored Aug 23, 2023
2 parents 844a030 + b160155 commit 6f2bac5
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 7 deletions.
18 changes: 15 additions & 3 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import React from 'react';
import { AuthProvider } from './src/context/AuthContext';
import Toast from 'react-native-toast-message';
import Index from './src/Index';
import { applyMiddleware, compose, createStore } from 'redux';
import reducers from './src/reducers';
import { Provider } from 'react-redux';
import createSagaMiddleware from '@redux-saga/core';
import rootSaga from './src/sagas/rootSaga';

const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware];
const store = compose(applyMiddleware(...middleware))(createStore)(reducers);
sagaMiddleware.run(rootSaga);

const App = () => {
return (
<>
<AuthProvider>
<Index />
</AuthProvider>
<Provider store={store}>
<AuthProvider>
<Index />
</AuthProvider>
</Provider>
<Toast />
</>
);
Expand Down
40 changes: 40 additions & 0 deletions __tests__/Util-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
updateStatus,
} from '../src/screens/AuthScreen/Util';
import { urls } from '../src/constants/appConstant/url';
import { fetchUserRequest } from '../src/sagas/handlers/user';
import { fetchUserData } from '../src/sagas/requests/fetchUser';
import { call, put } from 'redux-saga/effects';
import Strings from '../src/i18n/en';
import axios from 'axios';

Expand Down Expand Up @@ -133,3 +136,40 @@ test('check is otpcode of valid format', () => {
expect(isValidTextInput('AB12')).toBeFalsy();
expect(isValidTextInput('1%2B')).toBeFalsy();
});

describe('fetchUserRequest', () => {
const action = { type: 'GET_USER', payload: 'lDaUIVTP4sXRwPWh3Gn4' };
const generator = fetchUserRequest(action);

test('should call fetchUserData', () => {
expect(generator.next().value).toEqual(call(fetchUserData, action.payload));
});

test('should dispatch FETCH_USER action', () => {
const user = {
company: 'Deloitte',
designation: 'Frontend Developer',
githubUrl: 'https://twitter.combharati-21',
linkedInUrl: 'https://www.linkedin.com/in/bharati-subramanian-29734b152',
name: 'Bharati Subramanian',
profileUrl:
'https://res.cloudinary.com/realdevsquad/image/upload/v1687759892/profile/lDaUIVTP4sXRwPWh3Gn4/sqaq4clqiprmdwu2lyjk.jpg',
twitterUrl: 'https://github.com/_bhaaratii',
userName: 'bharati',
};
expect(generator.next(user).value).toEqual(
put({ type: 'FETCH_USER', user }),
);
});

test('should dispatch FETCH_USER_ERROR action on error', () => {
const error = new Error('Something went wrong');
expect(generator.throw(error).value).toEqual(
put({ type: 'FETCH_USER_ERROR', message: error.message }),
);
});

test('should be done', () => {
expect(generator.next().done).toBe(true);
});
});
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@
"react-native-safe-area-context": "^3.2.0",
"react-native-screens": "^3.9.0",
"react-native-toast-message": "^2.1.5",
"react-native-webview": "^11.13.0"
"react-native-webview": "^11.13.0",
"react-redux": "^8.1.1",
"redux": "^4.2.1",
"redux-saga": "^1.2.3",
"react-native-vision-camera": "^2.15.4"
},
"devDependencies": {
"@babel/core": "^7.12.9",
Expand Down
6 changes: 6 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const getUser = (userId: string) => {
return {
type: 'GET_USER',
payload: userId,
};
};
5 changes: 5 additions & 0 deletions src/constants/appConstant/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ export const urls = {
API_ENDPOINT: 'https://api.realdevsquad.com/',
REDIRECT_URL: 'https://www.realdevsquad.com/goto',
GET_USERS_DATA: 'https://api.realdevsquad.com/users/self',
GET_USER_DATA: 'https://api.realdevsquad.com/users?id=',
GET_CONTRIBUTIONS: 'https://api.realdevsquad.com/contributions/',
GITHUB: 'https://github.com/',
TWITTER: 'https://twitter.com',
LINKEDIN: 'https://www.linkedin.com/in/',
};
11 changes: 11 additions & 0 deletions src/context/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,14 @@ export type loggedInUserType = {
profileUrl: string;
status: string;
};

export interface User {
name: string;
profileUrl: string;
userName: string;
designation: string;
company: string;
linkedInUrl: string;
twitterUrl: string;
githubUrl: string;
}
6 changes: 6 additions & 0 deletions src/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { combineReducers } from 'redux';
import user from './user.reducer';

const reducers = combineReducers({ user });

export default reducers;
20 changes: 20 additions & 0 deletions src/reducers/user.reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const intialState = {
data: {},
loading: false,
error: '',
};

const user = (state = intialState, action) => {
switch (action.type) {
case 'FETCH_USER':
return { ...state, loading: false, data: action.user };
case 'GET_USER':
return { ...state, loading: true };
case 'FETCH_USER_ERROR':
return { ...state, loading: false, error: action.message };
default:
return state;
}
};

export default user;
18 changes: 18 additions & 0 deletions src/sagas/handlers/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { call, put, takeEvery } from 'redux-saga/effects';
import { User } from '../../context/type';
import { fetchUserData } from '../requests/fetchUser';

export function* fetchUserRequest(action) {
try {
const user: User = yield call(fetchUserData, action.payload);
yield put({ type: 'FETCH_USER', user: user });
} catch (error: any) {
yield put({ type: 'FETCH_USER_ERROR', message: error.message });
}
}

function* watchUserRequestSaga() {
yield takeEvery('GET_USER', fetchUserRequest);
}

export default watchUserRequestSaga;
26 changes: 26 additions & 0 deletions src/sagas/requests/fetchUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import axios from 'axios';
import { urls } from '../../constants/appConstant/url';
import { User } from '../../context/type';

export const fetchUserData = async (userId: string): Promise<User | null> => {
try {
const response = await axios.get(urls.GET_USER_DATA + userId, {
headers: {
cookie: '',
},
});
const user = response.data.user;
return {
name: user.github_display_name,
profileUrl: user.picture?.url,
userName: user.username,
designation: user.designation,
company: user.company,
linkedInUrl: urls.LINKEDIN + user.linkedin_id,
twitterUrl: urls.GITHUB + user.twitter_id,
githubUrl: urls.TWITTER + user.github_id,
};
} catch (error) {
throw error;
}
};
8 changes: 8 additions & 0 deletions src/sagas/rootSaga.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { all } from 'redux-saga/effects';
import watchUserRequestSaga from './handlers/user';

function* rootSaga() {
yield all([watchUserRequestSaga()]);
}

export default rootSaga;
13 changes: 13 additions & 0 deletions src/screens/AuthScreen/Util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ export const getUserData = async (url: string) => {
}
};

export const fetchContribution = async (userName: string): Promise<any> => {
try {
const response = await axios.get(urls.GET_CONTRIBUTIONS + userName, {
headers: {
cookie: '',
},
});
return response.data;
} catch (error) {
return null;
}
};

export const updateStatus = async (status: string) => {
const res = await axios.patch(
urls.GET_USERS_DATA,
Expand Down
11 changes: 10 additions & 1 deletion src/screens/HomeScreen/HomeScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { AuthContext } from '../../context/AuthContext';
import withHeader from '../../helpers/withHeader';
Expand All @@ -7,9 +7,12 @@ import Strings from '../../i18n/en';
import { updateStatus } from '../AuthScreen/Util';
import { HomeViewStyle } from './styles';
import Toast from 'react-native-toast-message';
import { useDispatch } from 'react-redux';
import { getUser } from '../../actions';

const HomeScreen = () => {
const [loader, setLoader] = useState<boolean>(false);
const dispatch = useDispatch();

const { loggedInUserData, setLoggedInUserData } = useContext(AuthContext);

Expand Down Expand Up @@ -75,6 +78,12 @@ const HomeScreen = () => {
</View>
);
};

useEffect(() => {
// TODO: get the userId from global store
dispatch(getUser('lDaUIVTP4sXRwPWh3Gn4'));
}, [dispatch]);

return <View style={HomeViewStyle.container}>{renderScreen()}</View>;
};

Expand Down
21 changes: 21 additions & 0 deletions src/screens/ProfileScreen/ProfileScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO: we wil remove this once we start using userData and contributionData
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { useState, useCallback, useContext } from 'react';
import { View, Text, Pressable } from 'react-native';
import { ScreenViewContainer } from '../../styles/GlobalStyle';
Expand All @@ -9,10 +11,19 @@ import UploadImageModalView from '../../components/GalleryModal';
import { AuthContext } from '../../context/AuthContext';
import { ImagePickerResponse } from 'react-native-image-picker';
import Strings from '../../i18n/en';
import { fetchContribution } from '../AuthScreen/Util';
import { useFocusEffect } from '@react-navigation/native';

import { useSelector } from 'react-redux';

const ProfileScreen = () => {
const { data: userData } = useSelector((store) => store.user);
const [response, setResponse] = useState<ImagePickerResponse>({});
const [modalVisible, setModalVisible] = useState(false);
const [contributionData, setContributionData] = useState({
allData: [],
noteworthy: [],
});
const { loggedInUserData, setLoggedInUserData } = useContext(AuthContext);
console.log('loggedIn', loggedInUserData);

Expand All @@ -36,6 +47,16 @@ const ProfileScreen = () => {
return true;
};

useFocusEffect(
useCallback(() => {
(async () => {
const userName = 'ankush';
const contributionResponse = await fetchContribution(userName);
setContributionData(contributionResponse);
})();
}, []),
);

return (
<View style={ScreenViewContainer.container}>
<Pressable
Expand Down
Loading

0 comments on commit 6f2bac5

Please sign in to comment.