Create a Bill Splitter App using React-Native
We are going to implement the Bill Splitter App using React Native. Bill Splitter App is a mobile application that helps us divide expenses and bills among a group of people. For example, when we are dining at a restaurant with friends, going on a trip, or sharing household expenses with roommates.
Prerequisites:
Preview of final output: Let us have a look at how the final output will look like.
Approach:
- Bill Splitter App is a mobile application that helps us to split expenses and bills among a group of people.
- It takes the name and money spent by each individual.
- Then this App calculates the money equally among all.
- We also included a calculate button in the app so when the button is clicked it shows the Name from whom to take money or whom to give money.
- We also added a reset button in the app to reset the data.
Steps to Create React Native Application:
Step 1: Create a react native application by using this command in command prompt
React-native init BillSplitter
Project Structure:
Example:
- Emulator will open after this command, and after opening of emulator you are ready to work in vs code to write the code.
- Open the file and Simply paste the source code
Javascript
import React, { useState } from 'react' ; import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView } from 'react-native' ; const BillSplitter = () => { const [participants, setParticipants] = useState( [ { name: '' , amount: '' } ]); const [settleTransactions, setSettleTransactions] = useState([]); const addParticipant = () => { setParticipants( [...participants, { name: '' , amount: '' }]); }; const removeParticipant = (index) => { const updatedParticipants = [...participants]; updatedParticipants.splice(index, 1); setParticipants(updatedParticipants); }; const calculateSplit = () => { const totalExpense = participants.reduce( (total, participant) => total + parseFloat(participant.amount || 0), 0 ); const splitAmount = totalExpense / participants.length; const calculatedResults = participants.map((participant) => { const amount = (splitAmount - parseFloat(participant.amount)).toFixed(2); return { name: participant.name, amount: parseFloat(amount), }; }); const settleTransactions = []; let positiveBalances = calculatedResults.filter( (result) => result.amount > 0); let negativeBalances = calculatedResults.filter( (result) => result.amount < 0); while (positiveBalances.length > 0 && negativeBalances.length > 0) { const payer = positiveBalances[0]; const payee = negativeBalances[0]; const settledAmount = Math.min( Math.abs(payer.amount), Math.abs(payee.amount)); settleTransactions.push({ payer: payer.name, payee: payee.name, amount: settledAmount.toFixed(2), }); payer.amount -= settledAmount; payee.amount += settledAmount; if (Math.abs(payer.amount) < 0.005) { positiveBalances.shift(); } if (Math.abs(payee.amount) < 0.005) { negativeBalances.shift(); } } setSettleTransactions(settleTransactions); }; const resetApp = () => { setParticipants([{ name: '' , amount: '' }]); setSettleTransactions([]); }; return ( <View style={styles.container}> <Text style={styles.title}>Bill Splitter</Text> <ScrollView style={styles.participantList}> {participants.map((participant, index) => ( <View key={index} style={styles.participantItem}> <TextInput style={styles.input} placeholder= "Name" value={participant.name} onChangeText={(text) => { const updatedParticipants = [...participants]; updatedParticipants[index].name = text; setParticipants(updatedParticipants); }} /> <TextInput style={styles.input} placeholder= "Amount" value={participant.amount} onChangeText={(text) => { const updatedParticipants = [...participants]; updatedParticipants[index].amount = text; setParticipants(updatedParticipants); }} keyboardType= "numeric" /> <TouchableOpacity style={styles.removeButton} onPress={() => removeParticipant(index)} > <Text style={styles.removeButtonText}>Remove</Text> </TouchableOpacity> </View> ))} </ScrollView> <TouchableOpacity style={styles.addButton} onPress={addParticipant}> <Text style={styles.addButtonText}>Add Participant</Text> </TouchableOpacity> <TouchableOpacity style={styles.calculateButton} onPress={calculateSplit}> <Text style={styles.calculateButtonText}>Calculate</Text> </TouchableOpacity> <TouchableOpacity style={styles.resetButton} onPress={resetApp}> <Text style={styles.resetButtonText}>Reset</Text> </TouchableOpacity> { /* Settled Transactions Box */ } <View style={styles.resultBox}> <Text style={styles.resultsTitle}>Settle Transactions</Text> <ScrollView style={styles.resultsList}> {settleTransactions.map((transaction, index) => ( <Text key={index} style={styles.resultItem}> {transaction.payer} should pay {transaction.payee} ${transaction.amount} </Text> ))} </ScrollView> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: 'white' , }, title: { fontSize: 24, textAlign: 'center' , marginVertical: 20, }, participantList: { marginBottom: 20, }, participantItem: { flexDirection: 'row' , justifyContent: 'space-between' , marginVertical: 10, }, input: { flex: 1, height: 40, borderColor: 'gray' , borderWidth: 1, borderRadius: 5, paddingHorizontal: 10, }, addButton: { backgroundColor: '#007AFF' , padding: 15, borderRadius: 5, alignItems: 'center' , marginBottom: 10, }, addButtonText: { color: 'white' , fontSize: 16, }, calculateButton: { backgroundColor: '#34C759' , padding: 15, borderRadius: 5, alignItems: 'center' , }, calculateButtonText: { color: 'white' , fontSize: 16, }, resultsTitle: { fontSize: 20, marginVertical: 10, }, resultsList: { marginBottom: 20, }, resultItem: { fontSize: 16, }, resetButton: { backgroundColor: '#FF3B30' , padding: 15, borderRadius: 5, alignItems: 'center' , marginTop: 10, }, resetButtonText: { color: 'white' , fontSize: 16, }, removeButton: { backgroundColor: '#FF3B30' , padding: 10, borderRadius: 100, alignItems: 'center' , marginTop: 5, marginLeft: 5, }, removeButtonText: { color: 'white' , fontSize: 12, }, resultBox: { borderWidth: 1, borderColor: '#ddd' , borderRadius: 5, marginTop: 20, padding: 5, backgroundColor: '#CBF6B6' , elevation: 5, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.3, shadowRadius: 3, }, }); export default BillSplitter; |
Step to Run Application: Run the application using the following command from the root directory of the project.
- For android
React-native run-android
- For ios
React-native run-ios
Output: