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
We take content rights seriously. If you suspect this is your content, claim it here.
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
We take content rights seriously. If you suspect this is your content, claim it here.
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