Open In App

Create a Bill Splitter App using React-Native

Last Updated : 06 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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.

bill

Output Preview

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:

reactnativeProj

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:

bill

Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads