0% found this document useful (0 votes)
2 views

react-nativeappcode

The document is a React Native component for a Progress Calendar that allows users to track their daily expenses and monthly budget. It includes features such as adding purchases, viewing daily totals, and visualizing monthly spending progress with color-coded indicators. The component utilizes hooks for state management and displays a calendar interface with modal functionality for detailed expense entries.

Uploaded by

roshcode44
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

react-nativeappcode

The document is a React Native component for a Progress Calendar that allows users to track their daily expenses and monthly budget. It includes features such as adding purchases, viewing daily totals, and visualizing monthly spending progress with color-coded indicators. The component utilizes hooks for state management and displays a calendar interface with modal functionality for detailed expense entries.

Uploaded by

roshcode44
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 11

import React, { useState, useEffect } from "react";

import {
View,
Text,
TouchableOpacity,
ScrollView,
Modal,
StyleSheet,
StatusBar,
TextInput,
Alert,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Ionicons } from "@expo/vector-icons";

const ProgressCalendar = () => {


const [averageCost, setAverageCost] = useState(245);
const [currentDate, setCurrentDate] = useState(new Date(2025, 1));
const [selectedDay, setSelectedDay] = useState(null);
const [isModalVisible, setIsModalVisible] = useState(false);
const [monthlyBudget, setMonthlyBudget] = useState(5000);
const [purchaseData, setPurchaseData] = useState({
"2025-02-01": [
{ id: 1, description: "Monthly Rent", amount: 1200.0 },
{ id: 2, description: "Internet Bill", amount: 75.0 },
],
"2025-02-03": [
{ id: 3, description: "Grocery Shopping", amount: 125.5 },
{ id: 4, description: "Gym Membership", amount: 45.0 },
],
});
const [newDescription, setNewDescription] = useState("");
const [newAmount, setNewAmount] = useState("");
const [today, setToday] = useState(new Date());

const weekdaysShort = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];

useEffect(() => {
setToday(new Date());
}, []);

const isToday = (day) => {


const date = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
day
);
return date.toDateString() === today.toDateString();
};

const getDailyTotal = (date) => {


const dateString = date.toISOString().split("T")[0];
const purchases = purchaseData[dateString] || [];
return purchases.reduce((sum, purchase) => sum + purchase.amount, 0);
};

const getProgressColor = (day) => {


const date = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
day
);
const total = getDailyTotal(date);
if (total === 0) return "#6b7280";
if (total < averageCost * 0.5) return "#22c55e";
if (total < averageCost) return "#eab308";
return "#ef4444";
};

const getDaysInMonth = (date) => {


const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
return lastDay.getDate();
};

const getFirstDayOfMonth = (date) => {


return new Date(date.getFullYear(), date.getMonth(), 1).getDay();
};

const getPreviousMonthDays = (date) => {


const firstDay = getFirstDayOfMonth(date);
const prevMonthLastDay = new Date(
date.getFullYear(),
date.getMonth(),
0
).getDate();
return Array.from(
{ length: firstDay },
(_, i) => prevMonthLastDay - firstDay + i + 1
);
};

const handleDayPress = (day) => {


const date = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
day
);
setSelectedDay(date);
setIsModalVisible(true);
};

const handlePrevMonth = () => {


setCurrentDate(
new Date(currentDate.getFullYear(), currentDate.getMonth() - 1)
);
};

const handleNextMonth = () => {


setCurrentDate(
new Date(currentDate.getFullYear(), currentDate.getMonth() + 1)
);
};

const handleAddPurchase = () => {


if (newDescription.trim() === "" || newAmount.trim() === "") {
Alert.alert("Error", "Both fields are required.");
return;
}
const dateString = selectedDay?.toISOString().split("T")[0];
const newPurchase = {
id: Math.random(),
description: newDescription,
amount: parseFloat(newAmount),
};

setPurchaseData((prevData) => ({
...prevData,
[dateString]: [...(prevData[dateString] || []), newPurchase],
}));

setNewDescription("");
setNewAmount("");
};

const getMonthlyTotalSpent = () => {


const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth();
let totalSpent = 0;

Object.entries(purchaseData).forEach(([dateString, purchases]) => {


const purchaseDate = new Date(dateString);
if (
purchaseDate.getFullYear() === currentYear &&
purchaseDate.getMonth() === currentMonth
) {
totalSpent += purchases.reduce(
(sum, purchase) => sum + purchase.amount,
0
);
}
});

return totalSpent;
};

const MonthlyProgressBars = () => {


const totalSpent = getMonthlyTotalSpent();
const totalSaved =
monthlyBudget - totalSpent > 0 ? monthlyBudget - totalSpent : 0;

const spentPercentage = (totalSpent / monthlyBudget) * 100;


const savedPercentage = (totalSaved / monthlyBudget) * 100;

return (
<View style={styles.progressContainer}>
<Text style={styles.progressTitle}>Monthly Progress</Text>
<View style={styles.progressBarContainer}>
<View style={styles.progressLabelContainer}>
<Text style={styles.progressLabel}>Total
Spent</Text>
<Text style={styles.progressAmount}>
${totalSpent.toFixed(2)} / $
{monthlyBudget.toFixed(2)}
</Text>
</View>
<View style={styles.progressBarBackground}>
<View
style={[
styles.progressBarFill,
{ width: `${spentPercentage}%`,
backgroundColor: "#ef4444" },
]}
/>
</View>
</View>
<View style={styles.progressBarContainer}>
<View style={styles.progressLabelContainer}>
<Text style={styles.progressLabel}>Total
Saved</Text>
<Text style={styles.progressAmount}>
${totalSaved.toFixed(2)} / $
{monthlyBudget.toFixed(2)}
</Text>
</View>
<View style={styles.progressBarBackground}>
<View
style={[
styles.progressBarFill,
{ width: `${savedPercentage}%`,
backgroundColor: "#22c55e" },
]}
/>
</View>
</View>
</View>
);
};

return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<ScrollView contentContainerStyle={styles.scrollContent}>
<Text style={styles.title}>Progress Calendar</Text>

<View style={styles.calendarHeader}>
<TouchableOpacity onPress={handlePrevMonth}>
<Ionicons name="chevron-back" size={24}
color="white" />
</TouchableOpacity>
<Text style={styles.monthYearText}>
{currentDate.toLocaleString("default", {
month: "long",
year: "numeric",
})}
</Text>
<TouchableOpacity onPress={handleNextMonth}>
<Ionicons name="chevron-forward" size={24}
color="white" />
</TouchableOpacity>
</View>

<View style={styles.calendar}>
{weekdaysShort.map((day) => (
<View key={day} style={styles.weekdayLabel}>
<Text
style={styles.weekdayText}>{day}</Text>
</View>
))}

{getPreviousMonthDays(currentDate).map((day) => (
<View key={`prev-${day}`}
style={styles.dayContainer}>
<Text
style={styles.prevMonthDay}>{day}</Text>
</View>
))}

{Array.from(
{ length: getDaysInMonth(currentDate) },
(_, i) => i + 1
).map((day) => (
<TouchableOpacity
key={day}
style={[
styles.dayContainer,
isToday(day) &&
styles.todayHighlight,
]}
onPress={() => handleDayPress(day)}
>
<Text style={styles.dayText}>{day}</Text>
<View
style={[
styles.progressIndicator,
{ backgroundColor:
getProgressColor(day) },
]}
/>
</TouchableOpacity>
))}
</View>

<View style={styles.costBudgetInputContainer}>
<Text style={styles.costBudgetLabel}>Average
cost:</Text>
<TextInput
style={styles.input}
keyboardType="numeric"
onChangeText={(value) =>
setAverageCost(Number(value))}
value={String(averageCost)}
/>
</View>

<View style={styles.costBudgetInputContainer}>
<Text style={styles.costBudgetLabel}>Monthly
budget:</Text>
<TextInput
style={styles.input}
keyboardType="numeric"
onChangeText={(value) =>
setMonthlyBudget(Number(value))}
value={String(monthlyBudget)}
/>
</View>

<MonthlyProgressBars />

<Modal
visible={isModalVisible}
transparent={true}
onRequestClose={() => setIsModalVisible(false)}
animationType="slide"
>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>
Total Spent on{" "}

{selectedDay?.toLocaleDateString("en-US", { weekday: "long" })},{" "}


{selectedDay?.getDate()}{" "}

{selectedDay?.toLocaleString("default", {
month: "long",
})}
</Text>
<Text style={styles.modalTotalAmount}>
${getDailyTotal(selectedDay || new
Date()).toFixed(2)}
</Text>
<ScrollView style={styles.modalList}>
{(

purchaseData[selectedDay?.toISOString().split("T")[0]] || []
).map((item) => (
<View key={item.id}
style={styles.modalListItem}>
<Text
style={styles.modalListItemText}>

{item.description}:
</Text>
<Text
style={styles.modalListItemAmount}>
$
{item.amount.toFixed(2)}
</Text>
</View>
))}
</ScrollView>
<View style={styles.inputRow}>
<TextInput
style={styles.newInput}
placeholder="Description"

placeholderTextColor="#9ca3af"
value={newDescription}

onChangeText={setNewDescription}
/>
<TextInput
style={styles.newInput}
placeholder="Amount"
placeholderTextColor="#9ca3af"
value={newAmount}
onChangeText={setNewAmount}
keyboardType="numeric"
/>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity
style={styles.addButton}
onPress={handleAddPurchase}
>
<Text
style={styles.addButtonText}>Add</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.closeButton}
onPress={() =>
setIsModalVisible(false)}
>
<Text
style={styles.closeButtonText}>Close</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</ScrollView>
</SafeAreaView>
);
};

const styles = StyleSheet.create({


container: {
flex: 1,
backgroundColor: "#111827",
},
scrollContent: {
padding: 16,
},
title: {
fontSize: 24,
fontWeight: "bold",
color: "white",
marginBottom: 25,
alignSelf: "center",
},
calendarHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 16,
},
monthYearText: {
fontSize: 18,
fontWeight: "500",
color: "white",
},
calendar: {
flexDirection: "row",
flexWrap: "wrap",
marginBottom: 16,
},
weekdayLabel: {
width: "14.28%",
alignItems: "center",
marginBottom: 8,
},
weekdayText: {
color: "#9ca3af",
fontSize: 14,
},
dayContainer: {
width: "13.28%",
height: 20,
aspectRatio: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#1f2937",
marginBottom: 8,
borderRadius: 6,
marginHorizontal: 2,
},
prevMonthDay: {
color: "#4b5563",
fontSize: 15,
},
dayText: {
color: "white",
fontSize: 15,
},
progressIndicator: {
width: "50%",
height: 4,
borderRadius: 2,
marginTop: 4,
},
costBudgetInputContainer: {
marginBottom: 16,
},
costBudgetLabel: {
color: "#9ca3af",
fontSize: 16,
marginBottom: 4,
},
input: {
backgroundColor: "#374151",
color: "#22c55e",
fontSize: 18,
padding: 8,
borderRadius: 4,
},
progressContainer: {
backgroundColor: "#1f2937",
borderRadius: 8,
padding: 16,
marginTop: 16,
},
progressTitle: {
fontSize: 18,
fontWeight: "500",
color: "white",
marginBottom: 12,
},
progressBarContainer: {
marginBottom: 12,
},
progressLabelContainer: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 4,
},
progressLabel: {
color: "#9ca3af",
fontSize: 16,
paddingBottom: 5,
},
progressAmount: {
color: "white",
fontSize: 16,
},
progressBarBackground: {
height: 8,
backgroundColor: "#374151",
borderRadius: 4,
overflow: "hidden",
},
progressBarFill: {
height: "100%",
borderRadius: 4,
},
modalContainer: {
flex: 1,
backgroundColor: "rgba(0,0,0,0.75)",
justifyContent: "center",
alignItems: "center",
},
modalContent: {
width: "90%",
backgroundColor: "#1f2937",
borderRadius: 8,
padding: 16,
},
modalTitle: {
fontSize: 18,
color: "white",
marginBottom: 12,
textAlign: "center",
},
modalTotalAmount: {
fontSize: 38,
fontWeight: "bold",
color: "#22c55e",
textAlign: "center",
marginBottom: 8,
},
modalList: {
maxHeight: 200,
marginBottom: 8,
},
modalListItem: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 8,
padding: 8,
borderRadius: 4,
borderWidth: 1,
borderColor: "#6b7280",
backgroundColor: "#374151",
},
modalListItemText: {
color: "white",
},
modalListItemAmount: {
color: "#22c55e",
},
inputRow: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 8,
},
newInput: {
flex: 1,
backgroundColor: "#374151",
color: "white",
fontSize: 14,
padding: 8,
borderRadius: 4,
margin: 4,
},
buttonRow: {
flexDirection: "row",
justifyContent: "space-around",
marginTop: 8,
},
addButton: {
padding: 8,
paddingLeft: 20,
paddingRight: 20,
borderRadius: 4,
borderWidth: 1,
borderColor: "#22c55e",
},
addButtonText: {
color: "white",
fontSize: 14,
textAlign: "center",
},
closeButton: {
padding: 8,
paddingLeft: 16,
paddingRight: 16,
borderRadius: 4,
borderWidth: 1,
borderColor: "#6b7280",
},
closeButtonText: {
color: "white",
fontSize: 14,
textAlign: "center",
},
todayHighlight: {
backgroundColor: "#22c55e",
borderWidth: 2,
},
});

export default ProgressCalendar;

You might also like