From 11f3fbefb4f5aa8e4458c9f1c4487f9fd36bcad9 Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 18 Apr 2024 04:35:41 -0400 Subject: [PATCH] add redux store for portfolio to track new trades --- backend/src/services/portfolio.go | 3 - frontend/App.tsx | 3 +- frontend/components/LayoutWrapper.tsx | 2 + frontend/pages/Copy/CopyTradesPage.tsx | 9 ++- frontend/pages/Profile.tsx | 57 ++++++++++++------- .../reducers/portfolio/portfolioReducer.ts | 17 ++++++ frontend/services/etrade.ts | 8 --- 7 files changed, 65 insertions(+), 34 deletions(-) create mode 100644 frontend/reducers/portfolio/portfolioReducer.ts diff --git a/backend/src/services/portfolio.go b/backend/src/services/portfolio.go index 7f850f96..209ceacd 100644 --- a/backend/src/services/portfolio.go +++ b/backend/src/services/portfolio.go @@ -2,7 +2,6 @@ package services import ( "backend/src/models" - "fmt" "gorm.io/gorm" ) @@ -37,10 +36,8 @@ func (os *PortfolioService) CopyPortfolio(currentUserPortfolio models.UserPortfo // if position exists, update the quantity -> skip to next position if positionExists { - fmt.Println("position exists", matchingPosition.Ticker, matchingPosition.Quantity, position.Quantity) matchingPosition.Quantity += position.Quantity updatedPositions = append(updatedPositions, matchingPosition) - fmt.Println("position exists after", matchingPosition.Ticker, matchingPosition.Quantity, position.Quantity) continue } diff --git a/frontend/App.tsx b/frontend/App.tsx index e411770a..32e09a8f 100644 --- a/frontend/App.tsx +++ b/frontend/App.tsx @@ -3,15 +3,16 @@ import { Provider } from 'react-redux'; import { configureStore } from '@reduxjs/toolkit'; import onboardingReducer from './reducers/onboarding/onboardingReducer'; import makePostReducer from './reducers/makePost/makePostReducer'; +import portfolioReducer from './reducers/portfolio/portfolioReducer'; import LayoutWrapper from './components/LayoutWrapper'; import { ClerkProvider } from '@clerk/clerk-expo'; -//import 'react-native-gesture-handler'; import * as SecureStore from 'expo-secure-store'; const store = configureStore({ reducer: { onboarding: onboardingReducer, makePost: makePostReducer, + portfolio: portfolioReducer, }, }); diff --git a/frontend/components/LayoutWrapper.tsx b/frontend/components/LayoutWrapper.tsx index 0f8d4e21..36123c8c 100644 --- a/frontend/components/LayoutWrapper.tsx +++ b/frontend/components/LayoutWrapper.tsx @@ -5,6 +5,7 @@ import AuthNavigator from '../router/AuthNavigation'; import { configureStore } from '@reduxjs/toolkit'; import onboardingReducer from '../reducers/onboarding/onboardingReducer'; import makePostReducer from '../reducers/makePost/makePostReducer'; +import portfolioReducer from '../reducers/portfolio/portfolioReducer'; import { useSelector } from 'react-redux'; import MakePostNavigator from '../router/MakePostNavigation'; @@ -12,6 +13,7 @@ const store = configureStore({ reducer: { onboarding: onboardingReducer, makePost: makePostReducer, + portfolio: portfolioReducer, }, }); diff --git a/frontend/pages/Copy/CopyTradesPage.tsx b/frontend/pages/Copy/CopyTradesPage.tsx index 0fd839c8..42b89762 100644 --- a/frontend/pages/Copy/CopyTradesPage.tsx +++ b/frontend/pages/Copy/CopyTradesPage.tsx @@ -11,14 +11,17 @@ import { } from 'react-native'; import { useNavigation, useRoute } from '@react-navigation/native'; import { useSession } from '@clerk/clerk-expo'; +import { useDispatch } from 'react-redux'; import { ProfileNavigationProp, AuthNavigationProp, } from '../../types/navigationTypes'; import { CopyRouteParams } from '../../types/types'; import { copyTrades } from '../../services/copy'; +import { updatePortfolio } from '../../reducers/portfolio/portfolioReducer'; function CopyTradesPage() { + const dispatch = useDispatch(); const { session } = useSession(); const navigation = useNavigation(); const authNavigation = useNavigation(); @@ -37,15 +40,15 @@ function CopyTradesPage() { } try { - await copyTrades(session?.user.id as string, user?.id); - // Alert.alert(`session?.user.id: ${session?.user.id} | user.id: ${user?.id}`); + const copiedPortfolio = await copyTrades(session?.user.id as string, user?.id); + dispatch(updatePortfolio(copiedPortfolio)); } catch (error) { Alert.alert('Error', 'Failed to copy trades'); return; } Alert.alert('Success', 'Trades copied successfully'); - navigation.navigate('Profile'); + navigation.navigate('FollowerProfile', { user }); }; return ( diff --git a/frontend/pages/Profile.tsx b/frontend/pages/Profile.tsx index 1da798cb..1e62f50b 100644 --- a/frontend/pages/Profile.tsx +++ b/frontend/pages/Profile.tsx @@ -1,6 +1,6 @@ import { useNavigation, useRoute } from '@react-navigation/native'; import React, { useEffect, useState } from 'react'; -import { FlatList, Pressable, ScrollView, Text, View } from 'react-native'; +import { FlatList, Pressable, ScrollView, View } from 'react-native'; import { useSession } from '@clerk/clerk-expo'; import ProfileBanner from '../components/ProfileBanner'; import SubTabButton from '../components/SubTabButton'; @@ -10,28 +10,34 @@ import { ProfileActivityData } from '../constants'; import ProfilePerformance from '../components/ProfilePerformance'; import SignOut from '../components/SignOutButton'; import { getPortoflio } from '../services/etrade'; -import { ProfileRouteParams, UserPortfolio } from '../types/types'; +import { ProfileRouteParams } from '../types/types'; import { ProfilePositions } from '../components/ProfilePositions'; +import { useSelector } from 'react-redux'; +import { RootState } from '../components/LayoutWrapper'; +import { useDispatch } from 'react-redux'; +import { updatePortfolio } from '../reducers/portfolio/portfolioReducer'; // import SettingsSvg from '../assets/SettingsIcon.svg'; - - const Profile = () => { + const dispatch = useDispatch(); const { session } = useSession(); const navigation = useNavigation(); const [pageNumber, setPageNumber] = useState(0); - const [portfolio, setPortfolio] = useState() - const route = useRoute() - const isFollowerProfile = (route.params as ProfileRouteParams)?.user !== undefined; + const route = useRoute(); + const isFollowerProfile = + (route.params as ProfileRouteParams)?.user !== undefined; const user = (route.params as ProfileRouteParams)?.user || session!.user!; + const {portfolio} = useSelector((state: RootState) => { + return state.portfolio; + }); const OnActivitySelected = () => { - setPageNumber(1) - } + setPageNumber(1); + }; const OnPortfolioSelected = () => { - setPageNumber(0) - } + setPageNumber(0); + }; useEffect(() => { // set the title of the page @@ -40,14 +46,26 @@ const Profile = () => { headerTitle: `@${user.username}`, headerTitleAlign: 'center', headerRight: () => ( - + ), headerLeft: () => ( navigation.goBack()}> - + ), - }) + }); return navigation.addListener('focus', () => { if (session?.user.username === undefined) { @@ -58,9 +76,11 @@ const Profile = () => { }, []); useEffect(() => { - getPortoflio(user.id).then(userPortfolio => { - setPortfolio(userPortfolio) - }) + const fetchPortfolio = async () => { + const portfolio = await getPortoflio(user.id); + dispatch(updatePortfolio(portfolio)); + }; + fetchPortfolio(); }, []); return ( @@ -120,10 +140,9 @@ const Profile = () => { - {user.username} ); }; -export default Profile; \ No newline at end of file +export default Profile; diff --git a/frontend/reducers/portfolio/portfolioReducer.ts b/frontend/reducers/portfolio/portfolioReducer.ts new file mode 100644 index 00000000..9ffed7ef --- /dev/null +++ b/frontend/reducers/portfolio/portfolioReducer.ts @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { UserPortfolio } from '../../types/types'; + +const onboardingSlice = createSlice({ + name: 'onboarding', + initialState: { + portfolio: null as UserPortfolio | null, + }, + reducers: { + updatePortfolio(state, action) { + state.portfolio = action.payload; + }, + }, +}); + +export const { updatePortfolio } = onboardingSlice.actions; +export default onboardingSlice.reducer; diff --git a/frontend/services/etrade.ts b/frontend/services/etrade.ts index e40b7df8..a10db737 100644 --- a/frontend/services/etrade.ts +++ b/frontend/services/etrade.ts @@ -35,14 +35,6 @@ export const getPortoflio = async (id: string): Promise => { return response.data; } -// export const copyPortfolio = async (id: string, portfolio: UserPortfolio): Promise => { -// const response: AxiosResponse = await axios.post( -// `http://${API_LINK}/etrade/portfolio/${id}`, -// portfolio, -// ); -// return response.status; -// } - export const makeOrder = async (id: string, ticker: string, quantity: number, type: string): Promise => { const response: AxiosResponse = await axios.post( `http://${API_LINK}/etrade/order/${id}`,