├── assets ├── images │ ├── icon.png │ ├── splash.png │ ├── favicon.png │ ├── react-logo.png │ ├── adaptive-icon.png │ ├── react-logo@2x.png │ ├── react-logo@3x.png │ └── partial-react-logo.png ├── fonts │ └── SpaceMono-Regular.ttf └── icons │ ├── dollar-sign.svg │ ├── netflix.svg │ ├── brand-uber.svg │ ├── wallet-credit-card.svg │ ├── spotify-logo-light.svg │ ├── shopping-cart-line.svg │ ├── dollar-line.svg │ ├── logo-figma.svg │ ├── bxl-airbnb.svg │ ├── add-money-wallet-icon.svg │ └── amazon-outlined.svg ├── finance-app-iphone.png ├── babel.config.js ├── constants ├── Colors.ts └── Icons.tsx ├── declarations.d.ts ├── data ├── income.json ├── expenses.json └── spending.json ├── tsconfig.json ├── .gitignore ├── types.ts ├── metro.config.js ├── app ├── (tabs) │ ├── transactions.tsx │ ├── profile.tsx │ ├── _layout.tsx │ └── index.tsx └── _layout.tsx ├── app.json ├── README.md ├── package.json ├── components ├── Header.tsx ├── IncomeBlock.tsx ├── SpendingBlock.tsx └── ExpenseBlock.tsx └── scripts └── reset-project.js /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/splash.png -------------------------------------------------------------------------------- /finance-app-iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/finance-app-iphone.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/react-logo.png -------------------------------------------------------------------------------- /assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /assets/images/react-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/react-logo@2x.png -------------------------------------------------------------------------------- /assets/images/react-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/react-logo@3x.png -------------------------------------------------------------------------------- /assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /assets/images/partial-react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzpradip/expo-finance-app-ui/HEAD/assets/images/partial-react-logo.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /constants/Colors.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | black: '#1A1A1A', 3 | grey: '#242424', 4 | white: '#FCFCFC', 5 | tintColor: '#723FEB', 6 | blue: '#97E0F7' 7 | }; 8 | -------------------------------------------------------------------------------- /declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.svg" { 2 | import React from "react"; 3 | import { SvgProps } from "react-native-svg"; 4 | const content: React.FC; 5 | export default content; 6 | } -------------------------------------------------------------------------------- /data/income.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "name": "Salary", 5 | "amount": "1,500.00" 6 | }, 7 | { 8 | "id": "2", 9 | "name": "Freelancing", 10 | "amount": "850.99" 11 | }, 12 | { 13 | "id": "3", 14 | "name": "Interest", 15 | "amount": "200.95" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "paths": { 6 | "@/*": [ 7 | "./*" 8 | ] 9 | } 10 | }, 11 | "include": [ 12 | "**/*.ts", 13 | "**/*.tsx", 14 | ".expo/types/**/*.ts", 15 | "expo-env.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb 17 | # The following patterns were generated by expo-cli 18 | 19 | expo-env.d.ts 20 | # @end expo-cli -------------------------------------------------------------------------------- /types.ts: -------------------------------------------------------------------------------- 1 | export interface ExpenseType { 2 | id: string; 3 | name: string; 4 | amount: string; 5 | percentage: string; 6 | } 7 | 8 | export interface IncomeType { 9 | id: string; 10 | name: string; 11 | amount: string; 12 | } 13 | 14 | export interface SpendingType { 15 | id: string; 16 | name: string; 17 | amount: string; 18 | date: string; 19 | } -------------------------------------------------------------------------------- /assets/icons/dollar-sign.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icons/netflix.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/expenses.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "name": "Housing", 5 | "amount": "955.75", 6 | "percentage": "61" 7 | }, 8 | { 9 | "id": "2", 10 | "name": "Food", 11 | "amount": "300.55", 12 | "percentage": "19" 13 | }, 14 | { 15 | "id": "3", 16 | "name": "Saving", 17 | "amount": "200.95", 18 | "percentage": "13" 19 | }, 20 | { 21 | "id": "4", 22 | "name": "Miscleneous", 23 | "amount": "70.95", 24 | "percentage": "5" 25 | } 26 | ] -------------------------------------------------------------------------------- /assets/icons/brand-uber.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require("expo/metro-config"); 2 | 3 | module.exports = (() => { 4 | const config = getDefaultConfig(__dirname); 5 | 6 | const { transformer, resolver } = config; 7 | 8 | config.transformer = { 9 | ...transformer, 10 | babelTransformerPath: require.resolve("react-native-svg-transformer") 11 | }; 12 | config.resolver = { 13 | ...resolver, 14 | assetExts: resolver.assetExts.filter((ext) => ext !== "svg"), 15 | sourceExts: [...resolver.sourceExts, "svg"] 16 | }; 17 | 18 | return config; 19 | })(); -------------------------------------------------------------------------------- /assets/icons/wallet-credit-card.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/(tabs)/transactions.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet, Text, View } from 'react-native' 2 | import React from 'react' 3 | import Colors from '@/constants/Colors' 4 | import { Stack } from 'expo-router' 5 | 6 | const Page = () => { 7 | return ( 8 | <> 9 | 10 | 11 | Transactions 12 | 13 | 14 | ) 15 | } 16 | 17 | export default Page 18 | 19 | const styles = StyleSheet.create({ 20 | container: { 21 | flex: 1, 22 | justifyContent: "center", 23 | alignItems: "center", 24 | backgroundColor: Colors.black, 25 | }, 26 | text: { 27 | color: Colors.white, 28 | }, 29 | }) -------------------------------------------------------------------------------- /app/(tabs)/profile.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet, Text, View } from "react-native"; 2 | import React from "react"; 3 | import Colors from "@/constants/Colors"; 4 | import { Stack } from "expo-router"; 5 | 6 | const Page = () => { 7 | return ( 8 | <> 9 | 10 | 11 | Profile 12 | 13 | 14 | ); 15 | }; 16 | 17 | export default Page; 18 | 19 | const styles = StyleSheet.create({ 20 | container: { 21 | flex: 1, 22 | justifyContent: "center", 23 | alignItems: "center", 24 | backgroundColor: Colors.black, 25 | }, 26 | text: { 27 | color: Colors.white, 28 | }, 29 | }); 30 | -------------------------------------------------------------------------------- /assets/icons/spotify-logo-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/spending.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "name": "AirBnB Rent", 5 | "amount": "529.99", 6 | "date": "2024-05-01" 7 | }, 8 | { 9 | "id": "2", 10 | "name": "Netflix", 11 | "amount": "10.99", 12 | "date": "2024-05-02" 13 | }, 14 | { 15 | "id": "3", 16 | "name": "Spotify", 17 | "amount": "5.99", 18 | "date": "2024-05-02" 19 | }, 20 | { 21 | "id": "4", 22 | "name": "Amazon", 23 | "amount": "234.69", 24 | "date": "2024-05-06" 25 | }, 26 | { 27 | "id": "5", 28 | "name": "Figma", 29 | "amount": "8.99", 30 | "date": "2024-05-09" 31 | }, 32 | { 33 | "id": "6", 34 | "name": "Online Shopping", 35 | "amount": "136.99", 36 | "date": "2024-05-012" 37 | } 38 | ] -------------------------------------------------------------------------------- /assets/icons/shopping-cart-line.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { useFonts } from 'expo-font'; 2 | import { Stack } from 'expo-router'; 3 | import * as SplashScreen from 'expo-splash-screen'; 4 | import { useEffect } from 'react'; 5 | import 'react-native-reanimated'; 6 | 7 | // Prevent the splash screen from auto-hiding before asset loading is complete. 8 | SplashScreen.preventAutoHideAsync(); 9 | 10 | export default function RootLayout() { 11 | const [loaded] = useFonts({ 12 | SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), 13 | }); 14 | 15 | useEffect(() => { 16 | if (loaded) { 17 | SplashScreen.hideAsync(); 18 | } 19 | }, [loaded]); 20 | 21 | if (!loaded) { 22 | return null; 23 | } 24 | 25 | return ( 26 | 27 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /assets/icons/dollar-line.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "expo-finance-app", 4 | "slug": "expo-finance-app", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "scheme": "myapp", 9 | "userInterfaceStyle": "automatic", 10 | "splash": { 11 | "image": "./assets/images/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "ios": { 16 | "supportsTablet": true 17 | }, 18 | "android": { 19 | "adaptiveIcon": { 20 | "foregroundImage": "./assets/images/adaptive-icon.png", 21 | "backgroundColor": "#ffffff" 22 | } 23 | }, 24 | "web": { 25 | "bundler": "metro", 26 | "output": "static", 27 | "favicon": "./assets/images/favicon.png" 28 | }, 29 | "plugins": [ 30 | "expo-router" 31 | ], 32 | "experiments": { 33 | "typedRoutes": true 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /constants/Icons.tsx: -------------------------------------------------------------------------------- 1 | import DollarIcon from "@/assets/icons/dollar-line.svg"; 2 | import WalletAddMoneyIcon from "@/assets/icons/add-money-wallet-icon.svg"; 3 | import WalletCardIcon from "@/assets/icons/wallet-credit-card.svg"; 4 | import AmazonIcon from "@/assets/icons/amazon-outlined.svg"; 5 | import UberIcon from "@/assets/icons/brand-uber.svg"; 6 | import AirbnbIcon from "@/assets/icons/bxl-airbnb.svg"; 7 | import DollarSignIcon from "@/assets/icons/dollar-sign.svg"; 8 | import FigmaIcon from "@/assets/icons/logo-figma.svg"; 9 | import ShoopingCartIcon from "@/assets/icons/shopping-cart-line.svg"; 10 | import SpotifyIcon from "@/assets/icons/spotify-logo-light.svg"; 11 | import NetflixIcon from "@/assets/icons/netflix.svg"; 12 | 13 | export { 14 | DollarIcon, 15 | WalletAddMoneyIcon, 16 | WalletCardIcon, 17 | AmazonIcon, 18 | UberIcon, 19 | AirbnbIcon, 20 | DollarSignIcon, 21 | FigmaIcon, 22 | ShoopingCartIcon, 23 | SpotifyIcon, 24 | NetflixIcon, 25 | }; 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Finance App in React Native with Expo Router 2 | 3 | This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app) to create a Finance App UI in React Native. Along with App UI, here I've implemented custom bottom tabbar navigator with expo router v3 and pie chart with [react native gifted charts](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts) package. 4 | 5 | Libraries used in this project 6 | 7 | - [Expo](https://expo.dev) 8 | - [React Native Gifted Charts](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts) 9 | - [React Native SVG Tansformer](https://github.com/kristerkari/react-native-svg-transformer) 10 | 11 | 12 | ## Get started 13 | 14 | 1. Install dependencies 15 | 16 | ```bash 17 | npm install 18 | ``` 19 | 20 | 2. Start the app 21 | 22 | ```bash 23 | npx expo start 24 | ``` 25 | 26 | ## App Screenshot 27 | ![Finance App in React Native with Expo Router](./finance-app-iphone.png) 28 | 29 | ## Watch it on YouTube 30 | 31 | This repository is part of a tutorial on my [YouTube channel](https://www.youtube.com/@itzpradip). Check out the complete tutorial on YouTube by clicking below. 👇 32 | 33 | [![Finance App UI in React Native with Expo Router Tutorial for Beginners](https://img.youtube.com/vi/MLVxvof54KA/0.jpg)](https://youtu.be/MLVxvof54KA) 34 | 35 | -------------------------------------------------------------------------------- /assets/icons/logo-figma.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icons/bxl-airbnb.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "expo-finance-app", 3 | "main": "expo-router/entry", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "start": "expo start", 7 | "reset-project": "node ./scripts/reset-project.js", 8 | "android": "expo start --android", 9 | "ios": "expo start --ios", 10 | "web": "expo start --web", 11 | "test": "jest --watchAll", 12 | "lint": "expo lint" 13 | }, 14 | "jest": { 15 | "preset": "jest-expo" 16 | }, 17 | "dependencies": { 18 | "@expo/vector-icons": "^14.0.2", 19 | "@react-navigation/native": "^6.0.2", 20 | "expo": "~51.0.17", 21 | "expo-constants": "~16.0.2", 22 | "expo-font": "~12.0.7", 23 | "expo-linear-gradient": "~13.0.2", 24 | "expo-linking": "~6.3.1", 25 | "expo-router": "~3.5.17", 26 | "expo-splash-screen": "~0.27.5", 27 | "expo-status-bar": "~1.12.1", 28 | "expo-system-ui": "~3.0.6", 29 | "expo-web-browser": "~13.0.3", 30 | "react": "18.2.0", 31 | "react-dom": "18.2.0", 32 | "react-native": "0.74.2", 33 | "react-native-gesture-handler": "~2.16.1", 34 | "react-native-gifted-charts": "^1.4.11", 35 | "react-native-reanimated": "~3.10.1", 36 | "react-native-safe-area-context": "4.10.1", 37 | "react-native-screens": "3.31.1", 38 | "react-native-svg": "15.2.0", 39 | "react-native-svg-transformer": "^1.4.0", 40 | "react-native-web": "~0.19.10" 41 | }, 42 | "devDependencies": { 43 | "@babel/core": "^7.20.0", 44 | "@types/jest": "^29.5.12", 45 | "@types/react": "~18.2.45", 46 | "@types/react-test-renderer": "^18.0.7", 47 | "jest": "^29.2.1", 48 | "jest-expo": "~51.0.3", 49 | "react-test-renderer": "18.2.0", 50 | "typescript": "~5.3.3" 51 | }, 52 | "private": true 53 | } 54 | -------------------------------------------------------------------------------- /components/Header.tsx: -------------------------------------------------------------------------------- 1 | import { Image, StyleSheet, Text, TouchableOpacity, View } from "react-native"; 2 | import React from "react"; 3 | import { SafeAreaView } from "react-native-safe-area-context"; 4 | import Colors from "@/constants/Colors"; 5 | 6 | const Header = () => { 7 | return ( 8 | 9 | 12 | 13 | 17 | 18 | Hi, Jenny 19 | 20 | Your Budget 21 | 22 | 23 | 24 | {}} 26 | style={styles.btnWrapper} 27 | > 28 | 29 | My Transactions 30 | 31 | 32 | 33 | 34 | ); 35 | }; 36 | 37 | export default Header; 38 | 39 | const styles = StyleSheet.create({ 40 | container: { 41 | flex: 1, 42 | backgroundColor: Colors.black, 43 | }, 44 | wrapper: { 45 | flexDirection: "row", 46 | justifyContent: "space-between", 47 | height: 70, 48 | alignItems: "center", 49 | paddingHorizontal: 20, 50 | }, 51 | userInfoWrapper: { 52 | flexDirection: "row", 53 | alignItems: "center", 54 | }, 55 | userImg: { 56 | height: 50, 57 | width: 50, 58 | borderRadius: 30, 59 | }, 60 | userTxtWrapper: { 61 | marginLeft:10, 62 | }, 63 | userText: { 64 | color: Colors.white, 65 | }, 66 | boldText: { 67 | fontWeight:'700', 68 | }, 69 | btnWrapper: { 70 | borderColor: "#666", 71 | borderWidth: 1, 72 | padding: 8, 73 | borderRadius: 10, 74 | }, 75 | btnText: { 76 | color: Colors.white, 77 | fontSize: 12, 78 | }, 79 | }); 80 | -------------------------------------------------------------------------------- /scripts/reset-project.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * This script is used to reset the project to a blank state. 5 | * It moves the /app directory to /app-example and creates a new /app directory with an index.tsx and _layout.tsx file. 6 | * You can remove the `reset-project` script from package.json and safely delete this file after running it. 7 | */ 8 | 9 | const fs = require('fs'); 10 | const path = require('path'); 11 | 12 | const root = process.cwd(); 13 | const oldDirPath = path.join(root, 'app'); 14 | const newDirPath = path.join(root, 'app-example'); 15 | const newAppDirPath = path.join(root, 'app'); 16 | 17 | const indexContent = `import { Text, View } from "react-native"; 18 | 19 | export default function Index() { 20 | return ( 21 | 28 | Edit app/index.tsx to edit this screen. 29 | 30 | ); 31 | } 32 | `; 33 | 34 | const layoutContent = `import { Stack } from "expo-router"; 35 | 36 | export default function RootLayout() { 37 | return ( 38 | 39 | 40 | 41 | ); 42 | } 43 | `; 44 | 45 | fs.rename(oldDirPath, newDirPath, (error) => { 46 | if (error) { 47 | return console.error(`Error renaming directory: ${error}`); 48 | } 49 | console.log('/app moved to /app-example.'); 50 | 51 | fs.mkdir(newAppDirPath, { recursive: true }, (error) => { 52 | if (error) { 53 | return console.error(`Error creating new app directory: ${error}`); 54 | } 55 | console.log('New /app directory created.'); 56 | 57 | const indexPath = path.join(newAppDirPath, 'index.tsx'); 58 | fs.writeFile(indexPath, indexContent, (error) => { 59 | if (error) { 60 | return console.error(`Error creating index.tsx: ${error}`); 61 | } 62 | console.log('app/index.tsx created.'); 63 | 64 | const layoutPath = path.join(newAppDirPath, '_layout.tsx'); 65 | fs.writeFile(layoutPath, layoutContent, (error) => { 66 | if (error) { 67 | return console.error(`Error creating _layout.tsx: ${error}`); 68 | } 69 | console.log('app/_layout.tsx created.'); 70 | }); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /assets/icons/add-money-wallet-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icons/amazon-outlined.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/IncomeBlock.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FlatList, 3 | ListRenderItem, 4 | StyleSheet, 5 | Text, 6 | TouchableOpacity, 7 | View, 8 | } from "react-native"; 9 | import React from "react"; 10 | import Colors from "@/constants/Colors"; 11 | import { IncomeType } from "@/types"; 12 | import { DollarIcon, WalletAddMoneyIcon, WalletCardIcon } from "@/constants/Icons"; 13 | import { Feather } from "@expo/vector-icons"; 14 | 15 | const IncomeBlock = ({ incomeList }: { incomeList: IncomeType[] }) => { 16 | const renderItem: ListRenderItem = ({ item }) => { 17 | let icon = ; 18 | if ( item.name == 'Freelancing' ) { 19 | icon = 20 | } else if (item.name == 'Interest') { 21 | icon = 22 | } 23 | 24 | let amount = item.amount.split("."); 25 | return ( 26 | 36 | 43 | 52 | {icon} 53 | 54 | {}}> 55 | 56 | 57 | 58 | {item.name} 59 | 60 | ${amount[0]}. 61 | {amount[1]} 62 | 63 | 64 | ); 65 | }; 66 | 67 | return ( 68 | 69 | 70 | My Income 71 | 72 | 78 | 79 | ); 80 | }; 81 | 82 | export default IncomeBlock; 83 | 84 | const styles = StyleSheet.create({}); 85 | -------------------------------------------------------------------------------- /app/(tabs)/_layout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Tabs } from "expo-router"; 3 | import { AntDesign, FontAwesome, SimpleLineIcons } from "@expo/vector-icons"; 4 | import { View } from "react-native"; 5 | import Colors from "@/constants/Colors"; 6 | import { StatusBar } from "expo-status-bar"; 7 | 8 | const Layout = () => { 9 | return ( 10 | <> 11 | 35 | ( 39 | 46 | 47 | 48 | ), 49 | }} 50 | /> 51 | ( 55 | 62 | 63 | 64 | ), 65 | }} 66 | /> 67 | ( 71 | 78 | 79 | 80 | ), 81 | }} 82 | /> 83 | 84 | 85 | 86 | ); 87 | }; 88 | 89 | export default Layout; 90 | -------------------------------------------------------------------------------- /components/SpendingBlock.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet, Text, View } from "react-native"; 2 | import React from "react"; 3 | import { SpendingType } from "@/types"; 4 | import Colors from "@/constants/Colors"; 5 | import { 6 | AirbnbIcon, 7 | AmazonIcon, 8 | DollarIcon, 9 | FigmaIcon, 10 | NetflixIcon, 11 | ShoopingCartIcon, 12 | SpotifyIcon, 13 | } from "@/constants/Icons"; 14 | 15 | const SpendingBlock = ({ spendingList }: { spendingList: SpendingType[] }) => { 16 | let icon = ; 17 | 18 | return ( 19 | 20 | 21 | July Spending 22 | 23 | 24 | {spendingList.map((item) => { 25 | if (item.name == "AirBnB Rent") { 26 | icon = ; 27 | } else if (item.name == "Netflix") { 28 | icon = ; 29 | } else if (item.name == "Spotify") { 30 | icon = ; 31 | } else if (item.name == "Amazon") { 32 | icon = ; 33 | } else if (item.name == "Figma") { 34 | icon = ; 35 | } else if (item.name == "Online Shopping") { 36 | icon = ( 37 | 38 | ); 39 | } 40 | 41 | return ( 42 | 43 | {icon} 44 | 45 | 46 | {item.name} 47 | {item.date} 48 | 49 | ${item.amount} 50 | 51 | 52 | ); 53 | })} 54 | 55 | ); 56 | }; 57 | 58 | export default SpendingBlock; 59 | 60 | const styles = StyleSheet.create({ 61 | spendingSectionWrapper: { 62 | marginVertical: 20, 63 | alignItems: "flex-start", 64 | }, 65 | sectionTitle: { 66 | color: Colors.white, 67 | fontSize: 16, 68 | marginBottom: 20, 69 | }, 70 | spendingWrapper: { 71 | flexDirection: "row", 72 | alignItems: "center", 73 | marginVertical: 10, 74 | }, 75 | iconWrapper: { 76 | backgroundColor: Colors.grey, 77 | padding: 15, 78 | borderRadius: 50, 79 | marginRight: 10, 80 | }, 81 | textWrapper: { 82 | flex: 1, 83 | flexDirection: "row", 84 | justifyContent: "space-between", 85 | alignItems: "center", 86 | }, 87 | itemName: { 88 | color: Colors.white, 89 | fontSize: 16, 90 | fontWeight: "600", 91 | }, 92 | }); 93 | -------------------------------------------------------------------------------- /app/(tabs)/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, StyleSheet, ScrollView } from "react-native"; 2 | import React from "react"; 3 | import Colors from "@/constants/Colors"; 4 | import { Stack } from "expo-router"; 5 | import Header from "@/components/Header"; 6 | import { PieChart } from "react-native-gifted-charts"; 7 | import ExpenseBlock from "@/components/ExpenseBlock"; 8 | import IncomeBlock from "@/components/IncomeBlock"; 9 | import SpendingBlock from "@/components/SpendingBlock"; 10 | import ExpenseList from '@/data/expenses.json'; 11 | import incomeList from '@/data/income.json'; 12 | import spendingList from '@/data/spending.json'; 13 | 14 | const Page = () => { 15 | const pieData = [ 16 | { 17 | value: 47, 18 | color: Colors.tintColor, 19 | focused: true, 20 | text: "47%", 21 | }, 22 | { 23 | value: 40, 24 | color: Colors.blue, 25 | text: "40%", 26 | }, 27 | { 28 | value: 16, 29 | color: Colors.white, 30 | text: "16%", 31 | }, 32 | { value: 3, color: "#FFA5BA", gradientCenterColor: "#FF7F97", text: "3%" }, 33 | ]; 34 | 35 | return ( 36 | <> 37 |
, 40 | }} 41 | /> 42 | 43 | 44 | 51 | 52 | 53 | My Expenses 54 | 55 | 58 | $1475.00 59 | 60 | 61 | 62 | { 73 | return ( 74 | 77 | 84 | 47% 85 | 86 | 87 | ); 88 | }} 89 | /> 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ); 102 | }; 103 | 104 | export default Page; 105 | 106 | const styles = StyleSheet.create({ 107 | container: { 108 | flex: 1, 109 | backgroundColor: Colors.black, 110 | paddingHorizontal: 20, 111 | }, 112 | }); 113 | -------------------------------------------------------------------------------- /components/ExpenseBlock.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FlatList, 3 | ListRenderItem, 4 | StyleSheet, 5 | Text, 6 | TouchableOpacity, 7 | View, 8 | } from "react-native"; 9 | import React from "react"; 10 | import { ExpenseType } from "@/types"; 11 | import Colors from "@/constants/Colors"; 12 | import { Feather } from "@expo/vector-icons"; 13 | 14 | const ExpenseBlock = ({ expenseList }: { expenseList: ExpenseType[] }) => { 15 | const renderItem: ListRenderItem> = ({ 16 | item, 17 | index, 18 | }) => { 19 | if (index == 0) { 20 | return ( 21 | {}}> 22 | 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | let amount = item.amount.split("."); 32 | 33 | return ( 34 | 47 | 60 | {item.name} 61 | 62 | 75 | ${amount[0]}. 76 | {amount[1]} 77 | 78 | 79 | 92 | {item.percentage}% 93 | 94 | 95 | 96 | ); 97 | }; 98 | 99 | const staticItem = [{ name: "Add Item" }]; 100 | 101 | return ( 102 | 103 | 109 | 110 | ); 111 | }; 112 | 113 | export default ExpenseBlock; 114 | 115 | const styles = StyleSheet.create({ 116 | addItemBtn: { 117 | flex: 1, 118 | borderWidth: 2, 119 | borderColor: "#666", 120 | borderStyle: "dashed", 121 | borderRadius: 10, 122 | marginRight: 20, 123 | padding:20, 124 | justifyContent: 'center', 125 | alignItems:'center' 126 | }, 127 | expenseBlock: { 128 | backgroundColor: Colors.tintColor, 129 | width: 100, 130 | padding: 15, 131 | borderRadius: 15, 132 | marginRight: 20, 133 | gap: 8, 134 | justifyContent: "space-between", 135 | alignItems: "flex-start", 136 | }, 137 | expenseBlockTxt1: { 138 | color: Colors.white, 139 | fontSize: 14, 140 | }, 141 | expenseBlockTxt2: { 142 | color: Colors.white, 143 | fontSize: 16, 144 | fontWeight: "600", 145 | }, 146 | expenseBlockTxt2Span: { 147 | fontSize: 12, 148 | fontWeight: "400", 149 | }, 150 | expenseBlock3View: { 151 | backgroundColor: "rgba(255, 255, 255, 0.2)", 152 | paddingHorizontal: 5, 153 | paddingVertical: 3, 154 | borderRadius: 10, 155 | }, 156 | }); 157 | --------------------------------------------------------------------------------