From 8e1fcced71c9f38e0f98f1641d55ab69ccdb2c96 Mon Sep 17 00:00:00 2001 From: dtroupe Date: Wed, 15 Jan 2025 16:17:24 -0800 Subject: [PATCH] add example ui and plaid sdk --- exampleRN76/App.tsx | 281 +++++++++++++++++++------------ exampleRN76/Styles.js | 48 ++++++ exampleRN76/ios/.xcode.env.local | 1 + exampleRN76/package-lock.json | 12 +- exampleRN76/package.json | 5 +- 5 files changed, 240 insertions(+), 107 deletions(-) create mode 100644 exampleRN76/Styles.js create mode 100644 exampleRN76/ios/.xcode.env.local diff --git a/exampleRN76/App.tsx b/exampleRN76/App.tsx index 125fe1b9..8c4d8954 100644 --- a/exampleRN76/App.tsx +++ b/exampleRN76/App.tsx @@ -1,118 +1,191 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - * - * @format - */ - import React from 'react'; -import type {PropsWithChildren} from 'react'; -import { - SafeAreaView, - ScrollView, - StatusBar, - StyleSheet, - Text, - useColorScheme, - View, -} from 'react-native'; - +import { Platform, TextInput, Text, TouchableOpacity, View } from 'react-native'; +import { styles } from './Styles'; // Adjust import if needed for the actual path import { - Colors, - DebugInstructions, - Header, - LearnMoreLinks, - ReloadInstructions, -} from 'react-native/Libraries/NewAppScreen'; + LinkExit, + LinkEvent, + LinkLogLevel, + LinkSuccess, + dismissLink, + LinkOpenProps, + usePlaidEmitter, + LinkIOSPresentationStyle, + LinkTokenConfiguration, + FinanceKitError, + create, + open, + syncFinanceKit, + submit, + SubmissionData, + EmbeddedLinkView, // Make sure this is imported +} from 'react-native-plaid-link-sdk'; -type SectionProps = PropsWithChildren<{ - title: string; -}>; +// EmbeddedLinkView for displaying once a token is entered +const EmbeddedView = ({ token }: { token: string }) => { + let content; -function Section({children, title}: SectionProps): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; - return ( - - - {title} + if (token) { + content = ( + + { + console.log('onEvent', event); + }} + onSuccess={(success: LinkSuccess) => { + console.log('onSuccess', success); + }} + onExit={(exit: LinkExit) => { + console.log('onExit', exit); + }} + style={styles.embedded} + /> + + ); + } else { + content = ( + + Enter Link Token - - {children} - - - ); + ); + } + + return {content}; +}; + +function isValidString(str: string): boolean { + return str && str.trim() !== ''; } -function App(): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; +function createLinkTokenConfiguration( + token: string, + noLoadingState: boolean = false +): LinkTokenConfiguration { + console.log(`token: ${token}`); + return { + token: token, + noLoadingState: noLoadingState, + }; +} - const backgroundStyle = { - backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, +function createSubmissionData(phoneNumber: string): SubmissionData { + return { + phoneNumber: phoneNumber, + }; +} + +function createLinkOpenProps(): LinkOpenProps { + return { + onSuccess: (success: LinkSuccess) => { + console.log('Success: ', success); + success.metadata.accounts.forEach(it => console.log('accounts', it)); + }, + onExit: (linkExit: LinkExit) => { + console.log('Exit: ', linkExit); + dismissLink(); + }, + iOSPresentationStyle: LinkIOSPresentationStyle.MODAL, + logLevel: LinkLogLevel.ERROR, + }; +} + +const PlaidLinkScreen = () => { + // Use event emitter to get real-time events during a Link Session. + usePlaidEmitter((event: LinkEvent) => { + console.log(event); + }); + + const [text, onChangeText] = React.useState(''); + const [disabled, setDisabled] = React.useState(true); + + const iOSVersionParts = String(Platform.Version).split('.'); + const [majorVersion, minorVersion] = iOSVersionParts.length >= 2 ? iOSVersionParts : [null, null]; + + const financeKitText = () => { + if (majorVersion && minorVersion) { + const majorInt = parseInt(majorVersion, 10); + const minorInt = parseInt(minorVersion, 10); + + if (majorInt > 17) { + return Sync FinanceKit; + } else if (majorInt === 17 && minorInt >= 4) { + return Sync FinanceKit; + } else { + return ( + + FinanceKit not supported on this version of iOS + + ); + } + } else { + return Invalid iOS version; + } }; return ( - - + - -
- -
- Edit App.tsx to change this - screen and then come back to see your edits. -
-
- -
-
- -
-
- Read the docs to discover what to do next: -
- -
- - - ); -} + { + if (isValidString(text)) { + const tokenConfiguration = createLinkTokenConfiguration(text); + create(tokenConfiguration); + setDisabled(false); + } + }} + > + Create Link + + { + const submissionData = createSubmissionData('415-555-0015'); + submit(submissionData); + }} + > + Submit Layer Phone Number + + { + const openProps = createLinkOpenProps(); + open(openProps); + setDisabled(true); + }} + > + Open Link + + { + const completionHandler = (error?: FinanceKitError) => { + if (error) { + console.error('Error:', error); + } else { + console.log('Sync completed successfully'); + } + }; + const requestAuthorizationIfNeeded = true; + syncFinanceKit(text, requestAuthorizationIfNeeded, completionHandler); + }} + > + {financeKitText()} + -const styles = StyleSheet.create({ - sectionContainer: { - marginTop: 32, - paddingHorizontal: 24, - }, - sectionTitle: { - fontSize: 24, - fontWeight: '600', - }, - sectionDescription: { - marginTop: 8, - fontSize: 18, - fontWeight: '400', - }, - highlight: { - fontWeight: '700', - }, -}); + {/* Embedded Link View below the buttons */} + + + ); +}; -export default App; +export default PlaidLinkScreen; diff --git a/exampleRN76/Styles.js b/exampleRN76/Styles.js new file mode 100644 index 00000000..28f07a7a --- /dev/null +++ b/exampleRN76/Styles.js @@ -0,0 +1,48 @@ +import { StyleSheet } from 'react-native'; +import { Colors } from 'react-native/Libraries/NewAppScreen'; + +export const styles = StyleSheet.create({ + button: { + elevation: 8, + backgroundColor: '#2196F3', + width: '90%', + margin: 4, + paddingVertical: 4, + fontSize: 16, + textAlign: 'center', + color: 'white', + borderRadius: 4, + alignSelf: 'center', + textTransform: 'uppercase', + overflow: 'hidden', + }, + disabledButton: { + elevation: 8, + backgroundColor: '#2196F3', + width: '90%', + margin: 4, + paddingVertical: 4, + fontSize: 16, + textAlign: 'center', + color: 'white', + borderRadius: 4, + alignSelf: 'center', + textTransform: 'uppercase', + overflow: 'hidden', + opacity: 0.5, + }, + input: { + height: 40, + margin: 12, + width: '90%', + alignSelf: 'center', + borderWidth: 1, + padding: 10, + borderColor: Colors.black, + }, + embedded: { + width: '95%', + alignSelf: 'center', + height: 360, + }, +}); diff --git a/exampleRN76/ios/.xcode.env.local b/exampleRN76/ios/.xcode.env.local new file mode 100644 index 00000000..43b1ee4e --- /dev/null +++ b/exampleRN76/ios/.xcode.env.local @@ -0,0 +1 @@ +export NODE_BINARY=/Users/dtroupe/.nvm/versions/node/v19.8.1/bin/node diff --git a/exampleRN76/package-lock.json b/exampleRN76/package-lock.json index c00af4d4..7bf20e7d 100644 --- a/exampleRN76/package-lock.json +++ b/exampleRN76/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.1", "dependencies": { "react": "18.3.1", - "react-native": "0.76.6" + "react-native": "0.76.6", + "react-native-plaid-link-sdk": "^12.0.0" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -10080,6 +10081,15 @@ } } }, + "node_modules/react-native-plaid-link-sdk": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/react-native-plaid-link-sdk/-/react-native-plaid-link-sdk-12.0.0.tgz", + "integrity": "sha512-EYWSHNGP/MIiNe1yWI6nUGMYBSV+RM3aKUDJUwn4Dj1ZCXuLT+2fOrLma5w83oI2uX5yK8zGt1hNWBVwzkEj6A==", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", diff --git a/exampleRN76/package.json b/exampleRN76/package.json index 875433f0..5aa1e8f4 100644 --- a/exampleRN76/package.json +++ b/exampleRN76/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "18.3.1", - "react-native": "0.76.6" + "react-native": "0.76.6", + "react-native-plaid-link-sdk": "^12.0.0" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -36,4 +37,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +}