├── .expo-shared └── assets.json ├── .gitignore ├── App.js ├── Todo.js ├── app.json ├── assets ├── favicon.png ├── icon.png └── splash.png ├── babel.config.js ├── package-lock.json └── package.json /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { StyleSheet, Dimensions, ScrollView, Text, TextInput, Button, View, SafeAreaView } from 'react-native'; 3 | import Todo from './Todo'; 4 | import {BarChart, LineChart} from "react-native-chart-kit"; 5 | import moment from 'moment'; 6 | 7 | const App = () => { 8 | const [description, setDescription] = useState(''); 9 | const [amount, setAmount] = useState(''); 10 | const [total, setTotal] = useState(0); 11 | const [data, setData] = useState([ 12 | { date: moment().format('LL'), amount: 2000 }, 13 | { date: moment().subtract(1, 'days').format('LL'), amount: 2500 }, 14 | { date: moment().subtract(1, 'days').format('LL'), amount: 3500 }, 15 | { date: moment().subtract(1, 'days').format('LL'), amount: 3500 }, 16 | { date: moment().subtract(1, 'days').format('LL'), amount: 3500 }, 17 | { date: moment().subtract(7, 'days').format('LL'), amount: 3500 }, 18 | { date: moment().subtract(6, 'days').format('LL'), amount: 3500 }, 19 | { date: moment().subtract(5, 'days').format('LL'), amount: 3500 }, 20 | { date: moment().subtract(4, 'days').format('LL'), amount: 3500 }, 21 | { date: moment().subtract(3, 'days').format('LL'), amount: 4500 }, 22 | { date: moment().subtract(2, 'days').format('LL'), amount: 5500 }, 23 | { date: moment().subtract(2, 'days').format('LL'), amount: 5500 }, 24 | ]) 25 | const [transformedData, setTransformedData] = useState([]); 26 | 27 | useEffect(() => { 28 | setTransformedData(transformData(groupBy(data, 'date'))); 29 | }, [data]) 30 | 31 | const groupBy = (array, key) => 32 | array.reduce((rv, x) => { 33 | (rv[x[key]] = rv[x[key]] || []).push(x); 34 | return rv; 35 | }, {}); 36 | 37 | const [gigs, setGigs] = useState([ 38 | { 39 | description: 'Freelance job with Qazi', 40 | amount: 499.99, 41 | timestamp: new Date() 42 | } 43 | ]); 44 | 45 | const getDates = () => transformedData.map(pair => pair.date); 46 | const getAmounts = () => transformedData.map(pair => pair.amount); 47 | const transformData = (groupedData) => { 48 | const transformedArray = []; 49 | 50 | Object.entries(groupedData).forEach(entry => { 51 | const total = entry[1].reduce((total, pair) => total + pair.amount, 0) 52 | transformedArray.push({ date: moment(entry[0]).format('MM/DD'), amount: total }) 53 | }) 54 | 55 | const sortedArray = transformedArray.sort((a, b) => moment(a['date']).diff(moment(b['date']))) 56 | 57 | return sortedArray; 58 | } 59 | 60 | console.log('DEBUG 🔥', data) 61 | console.log('The Dates ⏲️', getDates()) 62 | console.log('The Amounts ⏲️', getAmounts()) 63 | console.log('The GROUPED values are ⏲️', Object.entries(groupBy(data, 'date'))) 64 | console.log('The Total grouped value 👽', transformData(groupBy(data, 'date'))) 65 | 66 | useEffect(() => { 67 | setTotal(gigs.reduce((total, gig) => total+Number(gig.amount), 0)); 68 | }, [gigs]) 69 | 70 | const addGig = () => { 71 | setGigs([...gigs, { 72 | description: description, 73 | amount: amount 74 | }]); 75 | 76 | setData([ 77 | ...data, 78 | { 79 | date: moment().format('LL'), 80 | amount: Number(amount) 81 | } 82 | ]); 83 | 84 | setDescription(''); 85 | setAmount(''); 86 | } 87 | 88 | return ( 89 | 90 | 91 | 92 | Let's build a React Native App for Freelance Devs to Track Income 🚀 🚀 🚀 93 | 94 | 95 | Bezier Line Chart 96 | `rgba(255, 255, 255, ${opacity})`, 115 | labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`, 116 | style: { 117 | borderRadius: 16 118 | }, 119 | propsForDots: { 120 | r: "6", 121 | strokeWidth: "2", 122 | stroke: "#ffa726" 123 | } 124 | }} 125 | bezier 126 | style={{ 127 | marginVertical: 8, 128 | borderRadius: 16 129 | }} 130 | /> 131 | 132 | Total Income: ${total} 133 | setDescription(text)} 138 | /> 139 | setAmount(text)} 145 | /> 146 |