Ex.No.
2 CROSS PLATFORM APPLICATION FOR A SIMPLE EXPENSE MANAGER
Aim:
To build a cross platform application for a simple expense manager which allows
entering expenses and income on each day and displays category wise weekly income and
expense.
Algorithm:
Step 1: Initialize state variables for expenses, income, new expense input, total expense, and
category-wise weekly summary.
Step 2: On app load, retrieve saved income and expenses from AsyncStorage and update state.
Step 3: Allow the user to enter income and save it to both state and AsyncStorage.
Step 4: Allow the user to input expense details (name, amount, date, category).
Step 5:On clicking "Add Expense", validate the input, add it to the list, save to AsyncStorage,
and clear the input fields.
Step 6: Whenever expenses update, recalculate total expense and generate category-wise
weekly summary.
Step 7: Display expenses list, total expense, and weekly summary on the screen.
Step 8: Provide a reset button to clear all data from AsyncStorage and reset state, showing a
confirmation alert.
Step Action Result
App Loads previous
loadData() runs inside useEffect.
Launches income & expenses.
User enters saveIncome(amount) updates both UI and
Income saved locally.
Income AsyncStorage.
User adds addExpense() creates an object, stores in list, saves in Expense recorded &
Expense AsyncStorage. displayed.
useEffect triggers calculateTotalExpense() and Total & summary
Data Changes
calculateCategorySummary(). updated.
User clicks Data cleared, UI
resetData() wipes AsyncStorage and updates UI.
Reset resets.
Steps to Run the Program:
1. Install Node.js
2. Install Expo CLI globally
npm install -g expo-cli
3. Install Android Studio (for Android) or use Xcode (for iOS)
Create a New React Native Project (Expo)
expo init WalletlyExpenseManager
Choose:
blank (JavaScript) template.
4. Install AsyncStorage
Change directory:
cd WalletlyExpenseManager
Then install AsyncStorage:
expo install @react-native-async-storage/async-storage
5. Replace App.js Code
Open project in VS Code or any code editor.
• Open App.js
• Replace the entire content with the code
6. Run the App
expo start
View the App
• Press a to run on Android Emulator
• Press i to run on iOS Simulator
• Or scan the QR code using Expo Go on your real mobile device.
PROGRAM:
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, FlatList, StyleSheet, TouchableOpacity, Alert } from
'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const categories = ['Food', 'Transport', 'Salary', 'Entertainment', 'Other'];
export default function App() {
const [entries, setEntries] = useState([]);
const [amount, setAmount] = useState('');
const [category, setCategory] = useState(categories[0]);
const [type, setType] = useState('Expense');
const [date, setDate] = useState('');
const [summary, setSummary] = useState({});
useEffect(() => {
loadData();
}, []);
useEffect(() => {
calculateSummary();
}, [entries]);
const saveData = async (data) => {
try {
await AsyncStorage.setItem('entries', JSON.stringify(data));
} catch (error) {
console.log('Error saving data:', error);
}
};
const loadData = async () => {
try {
const data = await AsyncStorage.getItem('entries');
if (data) setEntries(JSON.parse(data));
} catch (error) {
console.log('Error loading data:', error);
}
};
const calculateSummary = () => {
const weekAgo = new Date();
weekAgo.setDate(weekAgo.getDate() - 7);
const result = {};
categories.forEach(cat => result[cat] = { income: 0, expense: 0 });
entries.forEach(entry => {
const entryDate = new Date(entry.date);
if (entryDate >= weekAgo) {
if (entry.type === 'Income') {
result[entry.category].income += entry.amount;
} else {
result[entry.category].expense += entry.amount;
}
}
});
setSummary(result);
};
const addEntry = () => {
if (!amount || !date) {
Alert.alert("Please enter both Amount and Date (YYYY-MM-DD).");
return;
}
const newEntry = {
id: Date.now().toString(),
amount: parseFloat(amount),
category,
type,
date
};
const updatedEntries = [...entries, newEntry];
setEntries(updatedEntries);
saveData(updatedEntries);
setAmount('');
setDate('');
};
const resetData = async () => {
try {
await AsyncStorage.removeItem('entries');
setEntries([]);
setSummary({});
} catch (error) {
console.log('Error resetting data:', error);
}
};
return (
<View style={styles.container}>
<Text style={styles.header}>Simple Expense Manager</Text>
<TextInput
style={styles.input}
placeholder="Amount"
keyboardType="numeric"
value={amount}
onChangeText={setAmount}
/>
<TextInput
style={styles.input}
placeholder="Date (YYYY-MM-DD)"
value={date}
onChangeText={setDate}
/>
<Text style={styles.label}>Select Category:</Text>
<View style={styles.buttonContainer}>
{categories.map(cat => (
<TouchableOpacity
key={cat}
style={[styles.categoryButton, category === cat && styles.selectedCategory]}
onPress={() => setCategory(cat)}
>
<Text style={styles.buttonText}>{cat}</Text>
</TouchableOpacity>
))}
</View>
<Text style={styles.label}>Type:</Text>
<View style={styles.buttonContainer}>
<Button title="Income" onPress={() => setType('Income')} />
<Button title="Expense" onPress={() => setType('Expense')} />
</View>
<Button title="Add Entry" onPress={addEntry} />
<Text style={styles.summaryHeader}>Weekly Summary</Text>
<FlatList
data={Object.keys(summary)}
keyExtractor={(item) => item}
renderItem={({ item }) => (
<Text style={styles.summaryItem}>
{item}: Income ₹{summary[item].income.toFixed(2)} | Expense
₹{summary[item].expense.toFixed(2)}
</Text>
)}
/>
<View style={{ marginTop: 20 }}>
<Button title="Reset All Data" color="red" onPress={resetData} />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 20, marginTop: 40 },
header: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, textAlign: 'center' },
input: { borderWidth: 1, borderColor: '#ccc', padding: 8, marginVertical: 5 },
label: { marginTop: 10, fontWeight: 'bold' },
buttonContainer: { flexDirection: 'row', flexWrap: 'wrap', marginTop: 10 },
categoryButton: { margin: 5, padding: 10, backgroundColor: '#f0f0f0', borderRadius: 5 },
selectedCategory: { backgroundColor: '#4CAF50' },
buttonText: { color: '#000' },
summaryHeader: { marginTop: 20, fontSize: 20, fontWeight: 'bold', textAlign: 'center' },
summaryItem: { padding: 5, fontSize: 16 }
});
Sample Inputs
1. Income Input
• Enter "10000" in the Enter Income input field.
• This will save your income as:
₹10000
2. Add Expense Entries
You can enter each expense one by one using the input fields.
Field Example Input
Expense Name Grocery Shopping
Amount 2000
Date 2025-04-16
Category Food
Then click Add Expense.
Field Example Input
Expense Name Bus Pass
Amount 500
Date 2025-04-15
Field Example Input
Category Transport
Then click Add Expense.
Field Example Input
Expense Name Freelance Payment
Amount 5000
Date 2025-04-14
Category Salary
Then click Add Expense.
Field Example Input
Expense Name Movie Ticket
Amount 800
Date 2025-04-17
Category Entertainment
Then click Add Expense.
Expected Output
• Total Expense will show:
Total Expense: ₹8300.00
• Category-wise Weekly Summary will look like:
Food: Income ₹2000.00 | Expense ₹0.00
Transport: Income ₹500.00 | Expense ₹0.00
Salary: Income ₹5000.00 | Expense ₹0.00
Entertainment: Income ₹800.00 | Expense ₹0.00
Other: Income ₹0.00 | Expense ₹0.00
2025-04-16 - Grocery Shopping: ₹2000 - Food
2025-04-15 - Bus Pass: ₹500 - Transport
2025-04-14 - Freelance Payment: ₹5000 - Salary
2025-04-17 - Movie Ticket: ₹800 - Entertainment
OUTPUT:
Result:
Thus a cross platform application for a simple expense manager was successfully
developed and the output was verified.