From 6af8d955d926fa25115426197bc612baea2f25df Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Sat, 1 Jul 2023 22:14:51 +0530 Subject: [PATCH 1/7] feat : integrated user and contribution api --- src/constants/appConstant/url.ts | 5 +++ src/context/type.ts | 11 ++++++ src/screens/AuthScreen/Util.ts | 37 +++++++++++++++++++++ src/screens/ProfileScreen/ProfileScreen.tsx | 31 +++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/src/constants/appConstant/url.ts b/src/constants/appConstant/url.ts index 7eec108c..58ac6a99 100644 --- a/src/constants/appConstant/url.ts +++ b/src/constants/appConstant/url.ts @@ -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/', }; diff --git a/src/context/type.ts b/src/context/type.ts index f70c9868..222f8e86 100644 --- a/src/context/type.ts +++ b/src/context/type.ts @@ -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; +} diff --git a/src/screens/AuthScreen/Util.ts b/src/screens/AuthScreen/Util.ts index 00e38640..f14e0b6c 100644 --- a/src/screens/AuthScreen/Util.ts +++ b/src/screens/AuthScreen/Util.ts @@ -1,5 +1,6 @@ import axios from 'axios'; import { urls } from '../../constants/appConstant/url'; +import { User } from '../../context/type'; export const getUserData = async (url: string) => { if (url === urls.REDIRECT_URL) { @@ -19,6 +20,42 @@ export const getUserData = async (url: string) => { } }; +export const fetchUserData = async (userId: string): Promise => { + 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) { + return null; + } +}; + +export const fetchContribution = async (userName: string): Promise => { + 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, diff --git a/src/screens/ProfileScreen/ProfileScreen.tsx b/src/screens/ProfileScreen/ProfileScreen.tsx index adc65460..a2e09701 100644 --- a/src/screens/ProfileScreen/ProfileScreen.tsx +++ b/src/screens/ProfileScreen/ProfileScreen.tsx @@ -9,10 +9,27 @@ import UploadImageModalView from '../../components/GalleryModal'; import { AuthContext } from '../../context/AuthContext'; import { ImagePickerResponse } from 'react-native-image-picker'; import Strings from '../../i18n/en'; +import { fetchContribution, fetchUserData } from '../AuthScreen/Util'; +import { User } from '../../context/type'; +import { useFocusEffect } from '@react-navigation/native'; const ProfileScreen = () => { const [response, setResponse] = useState({}); const [modalVisible, setModalVisible] = useState(false); + const [userDetails, setUserDetails] = useState({ + company: '', + designation: '', + githubUrl: '', + linkedInUrl: '', + name: '', + profileUrl: '', + twitterUrl: '', + userName: '', + }); + const [contributionData, setContributionData] = useState({ + allData: [], + noteworthy: [], + }); const { loggedInUserData, setLoggedInUserData } = useContext(AuthContext); const openModal = useCallback(() => { @@ -35,6 +52,20 @@ const ProfileScreen = () => { return true; }; + useFocusEffect( + useCallback(() => { + (async () => { + // TODO: get the userId from global store + const userId = 'lDaUIVTP4sXRwPWh3Gn4'; + const userName = 'ankush'; + const userResponse = await fetchUserData(userId); + const contributionResponse = await fetchContribution(userName); + setContributionData(contributionResponse); + setUserDetails(userResponse); + })(); + }, []), + ); + return ( {/* TODO: remove temp style & improve Logout btn style Issue #71 */} From e94dc1e2d04d6262d36cd310ed1d1cccc4ab9a9a Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Sat, 8 Jul 2023 13:32:46 +0530 Subject: [PATCH 2/7] feat - added redux-saga, can access user data globally --- App.tsx | 18 ++- package.json | 5 +- src/actions/index.ts | 6 + src/reducers/index.ts | 6 + src/reducers/user.reducer.ts | 20 ++++ src/sagas/handlers/user.ts | 18 +++ src/sagas/requests/fetchUser.ts | 26 ++++ src/sagas/rootSaga.ts | 8 ++ src/screens/GoalScreen/GoalScreen.tsx | 1 - src/screens/HomeScreen/HomeScreen.tsx | 11 +- src/screens/ProfileScreen/ProfileScreen.tsx | 20 +--- yarn.lock | 126 +++++++++++++++++--- 12 files changed, 228 insertions(+), 37 deletions(-) create mode 100644 src/actions/index.ts create mode 100644 src/reducers/index.ts create mode 100644 src/reducers/user.reducer.ts create mode 100644 src/sagas/handlers/user.ts create mode 100644 src/sagas/requests/fetchUser.ts create mode 100644 src/sagas/rootSaga.ts diff --git a/App.tsx b/App.tsx index 66423d98..b14cea8e 100644 --- a/App.tsx +++ b/App.tsx @@ -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 ( <> - - - + + + + + ); diff --git a/package.json b/package.json index d4cef88f..d3a005cc 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,10 @@ "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" }, "devDependencies": { "@babel/core": "^7.12.9", diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 00000000..cc30655f --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +1,6 @@ +export const getUser = (userId: string) => { + return { + type: 'GET_USER', + payload: userId, + }; +}; diff --git a/src/reducers/index.ts b/src/reducers/index.ts new file mode 100644 index 00000000..8dd7e2d0 --- /dev/null +++ b/src/reducers/index.ts @@ -0,0 +1,6 @@ +import { combineReducers } from 'redux'; +import user from './user.reducer'; + +const reducers = combineReducers({ user }); + +export default reducers; diff --git a/src/reducers/user.reducer.ts b/src/reducers/user.reducer.ts new file mode 100644 index 00000000..58628b58 --- /dev/null +++ b/src/reducers/user.reducer.ts @@ -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; diff --git a/src/sagas/handlers/user.ts b/src/sagas/handlers/user.ts new file mode 100644 index 00000000..960d3dc6 --- /dev/null +++ b/src/sagas/handlers/user.ts @@ -0,0 +1,18 @@ +import { call, put, takeEvery } from 'redux-saga/effects'; +import { User } from '../../context/type'; +import { fetchUserData } from '../requests/fetchUser'; + +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; diff --git a/src/sagas/requests/fetchUser.ts b/src/sagas/requests/fetchUser.ts new file mode 100644 index 00000000..4368a7f4 --- /dev/null +++ b/src/sagas/requests/fetchUser.ts @@ -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 => { + 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; + } +}; diff --git a/src/sagas/rootSaga.ts b/src/sagas/rootSaga.ts new file mode 100644 index 00000000..852ff676 --- /dev/null +++ b/src/sagas/rootSaga.ts @@ -0,0 +1,8 @@ +import { all } from 'redux-saga/effects'; +import watchUserRequestSaga from './handlers/user'; + +function* rootSaga() { + yield all([watchUserRequestSaga()]); +} + +export default rootSaga; diff --git a/src/screens/GoalScreen/GoalScreen.tsx b/src/screens/GoalScreen/GoalScreen.tsx index 2942b083..5003b232 100644 --- a/src/screens/GoalScreen/GoalScreen.tsx +++ b/src/screens/GoalScreen/GoalScreen.tsx @@ -32,7 +32,6 @@ function GoalsScreenStack() { - ); } diff --git a/src/screens/HomeScreen/HomeScreen.tsx b/src/screens/HomeScreen/HomeScreen.tsx index c1e37765..40e31d59 100644 --- a/src/screens/HomeScreen/HomeScreen.tsx +++ b/src/screens/HomeScreen/HomeScreen.tsx @@ -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'; @@ -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(false); + const dispatch = useDispatch(); const { loggedInUserData, setLoggedInUserData } = useContext(AuthContext); @@ -102,6 +105,12 @@ const HomeScreen = () => { ); }; + + useEffect(() => { + // TODO: get the userId from global store + dispatch(getUser('lDaUIVTP4sXRwPWh3Gn4')); + }, [dispatch]); + return {renderScreen()}; }; diff --git a/src/screens/ProfileScreen/ProfileScreen.tsx b/src/screens/ProfileScreen/ProfileScreen.tsx index 3b16fc24..af8492f9 100644 --- a/src/screens/ProfileScreen/ProfileScreen.tsx +++ b/src/screens/ProfileScreen/ProfileScreen.tsx @@ -9,23 +9,15 @@ import UploadImageModalView from '../../components/GalleryModal'; import { AuthContext } from '../../context/AuthContext'; import { ImagePickerResponse } from 'react-native-image-picker'; import Strings from '../../i18n/en'; -import { fetchContribution, fetchUserData } from '../AuthScreen/Util'; -import { User } from '../../context/type'; +import { fetchContribution } from '../AuthScreen/Util'; import { useFocusEffect } from '@react-navigation/native'; +import { useSelector } from 'react-redux'; + const ProfileScreen = () => { + const { user } = useSelector((store) => store); const [response, setResponse] = useState({}); const [modalVisible, setModalVisible] = useState(false); - const [userDetails, setUserDetails] = useState({ - company: '', - designation: '', - githubUrl: '', - linkedInUrl: '', - name: '', - profileUrl: '', - twitterUrl: '', - userName: '', - }); const [contributionData, setContributionData] = useState({ allData: [], noteworthy: [], @@ -55,13 +47,9 @@ const ProfileScreen = () => { useFocusEffect( useCallback(() => { (async () => { - // TODO: get the userId from global store - const userId = 'lDaUIVTP4sXRwPWh3Gn4'; const userName = 'ankush'; - const userResponse = await fetchUserData(userId); const contributionResponse = await fetchContribution(userName); setContributionData(contributionResponse); - setUserDetails(userResponse); })(); }, []), ); diff --git a/yarn.lock b/yarn.lock index d2cf0832..486579b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -722,6 +722,13 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== +"@babel/runtime@^7.12.1", "@babel/runtime@^7.6.3", "@babel/runtime@^7.9.2": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" @@ -1345,11 +1352,6 @@ resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.17.tgz#9cb95765940f2841916fc71686598c22a3e4067e" integrity sha512-sui8AzHm6TxeEvWT/NEXlz3egYvCUog4tlXA4Xlb2Vxvy3purVXDq/XsM56lJl344U5Aj/jDzkVanOTMWyk4UA== -"@react-navigation/elements@^1.3.17": - version "1.3.17" - resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.17.tgz#9cb95765940f2841916fc71686598c22a3e4067e" - integrity sha512-sui8AzHm6TxeEvWT/NEXlz3egYvCUog4tlXA4Xlb2Vxvy3purVXDq/XsM56lJl344U5Aj/jDzkVanOTMWyk4UA== - "@react-navigation/native-stack@^6.9.12": version "6.9.12" resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.12.tgz#a09fe43ab2fc4c82a1809e3953021d1da4ead85c" @@ -1358,14 +1360,6 @@ "@react-navigation/elements" "^1.3.17" warn-once "^0.1.0" -"@react-navigation/native@^6.0.8": - version "6.1.6" - resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.6.tgz#84ff5cf85b91f660470fa9407c06c8ee393d5792" - integrity sha512-14PmSy4JR8HHEk04QkxQ0ZLuqtiQfb4BV9kkMXD2/jI4TZ+yc43OnO6fQ2o9wm+Bq8pY3DxyerC2AjNUz+oH7Q== - dependencies: - "@react-navigation/elements" "^1.3.17" - warn-once "^0.1.0" - "@react-navigation/native@^6.0.8": version "6.1.6" resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.6.tgz#84ff5cf85b91f660470fa9407c06c8ee393d5792" @@ -1392,6 +1386,50 @@ color "^4.2.3" warn-once "^0.1.0" +"@redux-saga/core@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.2.3.tgz#882ed9ac58b5f42c6abb23349542315b871de305" + integrity sha512-U1JO6ncFBAklFTwoQ3mjAeQZ6QGutsJzwNBjgVLSWDpZTRhobUzuVDS1qH3SKGJD8fvqoaYOjp6XJ3gCmeZWgA== + dependencies: + "@babel/runtime" "^7.6.3" + "@redux-saga/deferred" "^1.2.1" + "@redux-saga/delay-p" "^1.2.1" + "@redux-saga/is" "^1.1.3" + "@redux-saga/symbols" "^1.1.3" + "@redux-saga/types" "^1.2.1" + redux "^4.0.4" + typescript-tuple "^2.2.1" + +"@redux-saga/deferred@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.2.1.tgz#aca373a08ccafd6f3481037f2f7ee97f2c87c3ec" + integrity sha512-cmin3IuuzMdfQjA0lG4B+jX+9HdTgHZZ+6u3jRAOwGUxy77GSlTi4Qp2d6PM1PUoTmQUR5aijlA39scWWPF31g== + +"@redux-saga/delay-p@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.2.1.tgz#e72ac4731c5080a21f75b61bedc31cb639d9e446" + integrity sha512-MdiDxZdvb1m+Y0s4/hgdcAXntpUytr9g0hpcOO1XFVyyzkrDu3SKPgBFOtHn7lhu7n24ZKIAT1qtKyQjHqRd+w== + dependencies: + "@redux-saga/symbols" "^1.1.3" + +"@redux-saga/is@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.1.3.tgz#b333f31967e87e32b4e6b02c75b78d609dd4ad73" + integrity sha512-naXrkETG1jLRfVfhOx/ZdLj0EyAzHYbgJWkXbB3qFliPcHKiWbv/ULQryOAEKyjrhiclmr6AMdgsXFyx7/yE6Q== + dependencies: + "@redux-saga/symbols" "^1.1.3" + "@redux-saga/types" "^1.2.1" + +"@redux-saga/symbols@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.1.3.tgz#b731d56201719e96dc887dc3ae9016e761654367" + integrity sha512-hCx6ZvU4QAEUojETnX8EVg4ubNLBFl1Lps4j2tX7o45x/2qg37m3c6v+kSp8xjDJY+2tJw4QB3j8o8dsl1FDXg== + +"@redux-saga/types@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" + integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== + "@rnx-kit/align-deps@^2.2.2": version "2.2.2" resolved "https://registry.yarnpkg.com/@rnx-kit/align-deps/-/align-deps-2.2.2.tgz#cc7b95b7dcd66bc254d47bcb61c8bd40bbac385d" @@ -1506,6 +1544,14 @@ resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa" integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA== +"@types/hoist-non-react-statics@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -1613,6 +1659,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/use-sync-external-store@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" + integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -3773,7 +3824,7 @@ hermes-profile-transformer@^0.0.6: dependencies: source-map "^0.7.3" -hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -6203,6 +6254,18 @@ react-native@0.66.4: whatwg-fetch "^3.0.0" ws "^6.1.4" +react-redux@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.1.1.tgz#8e740f3fd864a4cd0de5ba9cdc8ad39cc9e7c81a" + integrity sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA== + dependencies: + "@babel/runtime" "^7.12.1" + "@types/hoist-non-react-statics" "^3.3.1" + "@types/use-sync-external-store" "^0.0.3" + hoist-non-react-statics "^3.3.2" + react-is "^18.0.0" + use-sync-external-store "^1.0.0" + react-refresh@^0.4.0: version "0.4.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" @@ -6289,6 +6352,20 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redux-saga@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.2.3.tgz#7362f78a0235868daf1210f8862a95906ac018a1" + integrity sha512-HDe0wTR5nhd8Xr5xjGzoyTbdAw6rjy1GDplFt3JKtKN8/MnkQSRqK/n6aQQhpw5NI4ekDVOaW+w4sdxPBaCoTQ== + dependencies: + "@redux-saga/core" "^1.2.3" + +redux@^4.0.4, redux@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -7240,6 +7317,25 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typescript-compare@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" + integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== + dependencies: + typescript-logic "^0.0.0" + +typescript-logic@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" + integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== + +typescript-tuple@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" + integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== + dependencies: + typescript-compare "^0.0.2" + typescript@^4.4.4: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -7369,7 +7465,7 @@ use-subscription@^1.0.0: dependencies: use-sync-external-store "^1.2.0" -use-sync-external-store@^1.2.0: +use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== From 212ac71f7cae18baf922113999e89faf53f338cb Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Sat, 8 Jul 2023 13:47:51 +0530 Subject: [PATCH 3/7] fix - handling redux warning --- src/screens/ProfileScreen/ProfileScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/ProfileScreen/ProfileScreen.tsx b/src/screens/ProfileScreen/ProfileScreen.tsx index af8492f9..832a8733 100644 --- a/src/screens/ProfileScreen/ProfileScreen.tsx +++ b/src/screens/ProfileScreen/ProfileScreen.tsx @@ -15,7 +15,7 @@ import { useFocusEffect } from '@react-navigation/native'; import { useSelector } from 'react-redux'; const ProfileScreen = () => { - const { user } = useSelector((store) => store); + const { data: userData } = useSelector((store) => store.user); const [response, setResponse] = useState({}); const [modalVisible, setModalVisible] = useState(false); const [contributionData, setContributionData] = useState({ From 9b5c3c4fb1ad2eee2f58b22bced1cb1a0edb3034 Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Sat, 8 Jul 2023 13:49:05 +0530 Subject: [PATCH 4/7] refactor - removing fetch user data funcion from auth utils --- src/screens/AuthScreen/Util.ts | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/screens/AuthScreen/Util.ts b/src/screens/AuthScreen/Util.ts index f14e0b6c..411c4cc4 100644 --- a/src/screens/AuthScreen/Util.ts +++ b/src/screens/AuthScreen/Util.ts @@ -20,29 +20,6 @@ export const getUserData = async (url: string) => { } }; -export const fetchUserData = async (userId: string): Promise => { - 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) { - return null; - } -}; - export const fetchContribution = async (userName: string): Promise => { try { const response = await axios.get(urls.GET_CONTRIBUTIONS + userName, { From 75599ebb37aa7f193a9049e188840a9ca7a82310 Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Sat, 8 Jul 2023 15:06:50 +0530 Subject: [PATCH 5/7] test - added test case for get user data --- __tests__/Util-test.ts | 40 ++++++++++++++++++++++++++++++++++++++ src/sagas/handlers/user.ts | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/__tests__/Util-test.ts b/__tests__/Util-test.ts index da158061..4d6e74a3 100644 --- a/__tests__/Util-test.ts +++ b/__tests__/Util-test.ts @@ -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'; @@ -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); + }); +}); diff --git a/src/sagas/handlers/user.ts b/src/sagas/handlers/user.ts index 960d3dc6..585c1cc2 100644 --- a/src/sagas/handlers/user.ts +++ b/src/sagas/handlers/user.ts @@ -2,7 +2,7 @@ import { call, put, takeEvery } from 'redux-saga/effects'; import { User } from '../../context/type'; import { fetchUserData } from '../requests/fetchUser'; -function* fetchUserRequest(action) { +export function* fetchUserRequest(action) { try { const user: User = yield call(fetchUserData, action.payload); yield put({ type: 'FETCH_USER', user: user }); From 26bb4b05b31667f09f480f7dd483a0af1ee025cb Mon Sep 17 00:00:00 2001 From: SHREYA MISHRA <61110378+shreya-mishra@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:37:05 +0530 Subject: [PATCH 6/7] Update package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ac029627..08dfb983 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "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", + "redux-saga": "^1.2.3", + "react-native-vision-camera": "^2.15.4" }, "devDependencies": { "@babel/core": "^7.12.9", From 1292df26be2e91038bf0e12eee7f42708ab7a82e Mon Sep 17 00:00:00 2001 From: mohammadkhizerkhan Date: Wed, 9 Aug 2023 23:24:00 +0530 Subject: [PATCH 7/7] removing unused variable and adding todo --- src/screens/AuthScreen/Util.ts | 1 - src/screens/ProfileScreen/ProfileScreen.tsx | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/screens/AuthScreen/Util.ts b/src/screens/AuthScreen/Util.ts index 411c4cc4..792f712a 100644 --- a/src/screens/AuthScreen/Util.ts +++ b/src/screens/AuthScreen/Util.ts @@ -1,6 +1,5 @@ import axios from 'axios'; import { urls } from '../../constants/appConstant/url'; -import { User } from '../../context/type'; export const getUserData = async (url: string) => { if (url === urls.REDIRECT_URL) { diff --git a/src/screens/ProfileScreen/ProfileScreen.tsx b/src/screens/ProfileScreen/ProfileScreen.tsx index 442b3549..e3ecae3c 100644 --- a/src/screens/ProfileScreen/ProfileScreen.tsx +++ b/src/screens/ProfileScreen/ProfileScreen.tsx @@ -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';