restore repo
This commit is contained in:
parent
97e8ee6eb8
commit
f2a798ab18
30 changed files with 1627 additions and 2 deletions
324
components/ui/NewGrafico.jsx
Normal file
324
components/ui/NewGrafico.jsx
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { View, StyleSheet, Dimensions, Text, FlatList } from 'react-native';
|
||||
import * as SQLite from 'expo-sqlite';
|
||||
import { LineChart } from 'react-native-chart-kit';
|
||||
import { Modal, TouchableOpacity } from 'react-native';
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/it'; // Import Italian locale for moment
|
||||
|
||||
const VisualizzaDati = () => {
|
||||
const [data, setData] = useState([]);
|
||||
const [selectedTransactions, setSelectedTransactions] = useState([]);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [selectedDate, setSelectedDate] = useState('');
|
||||
const [currentWeek, setCurrentWeek] = useState(moment().startOf('week'));
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
fetchData();
|
||||
}, 1000); // Aggiorna ogni 1 secondi
|
||||
|
||||
return () => clearInterval(interval); // Pulisce l'intervallo quando il componente viene smontato
|
||||
}, []);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const db = await SQLite.openDatabaseAsync('moneyAppDB');
|
||||
|
||||
const result = await db.getAllAsync('SELECT * FROM transactions');
|
||||
const fetchedData = [];
|
||||
for (const row of result) {
|
||||
fetchedData.push(row);
|
||||
}
|
||||
|
||||
// Raggruppa i dati per data e calcola la somma degli importi per il grafico
|
||||
const groupedData = fetchedData.reduce((acc, curr) => {
|
||||
const date = curr.date;
|
||||
if (!acc[date]) {
|
||||
acc[date] = 0;
|
||||
}
|
||||
acc[date] += curr.amount;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Trasforma l'oggetto raggruppato in un array di oggetti e ordina per data
|
||||
const chartDataArray = Object.keys(groupedData)
|
||||
.map(date => ({
|
||||
date,
|
||||
amount: groupedData[date],
|
||||
}))
|
||||
.sort((a, b) => new Date(a.date.split('-').reverse().join('-')) - new Date(b.date.split('-').reverse().join('-')));
|
||||
|
||||
setData(chartDataArray);
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const getWeekData = () => {
|
||||
const startOfWeek = currentWeek.clone().startOf('week');
|
||||
const endOfWeek = currentWeek.clone().endOf('week');
|
||||
const weekDates = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
weekDates.push(startOfWeek.clone().add(i, 'days').format('DD-MM-YYYY'));
|
||||
}
|
||||
const weekData = weekDates.map(date => {
|
||||
const item = data.find(d => d.date === date);
|
||||
return {
|
||||
date,
|
||||
amount: item ? item.amount : 0,
|
||||
};
|
||||
});
|
||||
return weekData;
|
||||
};
|
||||
|
||||
const getCurrentWeekText = () => {
|
||||
moment.locale('it'); // Set moment locale to Italian
|
||||
const startOfWeek = currentWeek.clone().startOf('week').format('DD MMMM');
|
||||
const endOfWeek = currentWeek.clone().endOf('week').format('DD MMMM');
|
||||
return `${startOfWeek} al ${endOfWeek}`;
|
||||
};
|
||||
|
||||
const chartData = {
|
||||
labels: getWeekData().map(item => item.date),
|
||||
datasets: [
|
||||
{
|
||||
data: getWeekData().map(item => item.amount),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const handleDataPointClick = async (dataPoint) => {
|
||||
const date = chartData.labels[dataPoint.index];
|
||||
setSelectedDate(date);
|
||||
try {
|
||||
const db = await SQLite.openDatabaseAsync('moneyAppDB');
|
||||
const result = await db.getAllAsync(`SELECT * FROM transactions WHERE date = ?`, [date]);
|
||||
setSelectedTransactions(result);
|
||||
setModalVisible(true);
|
||||
} catch (error) {
|
||||
console.error('Error fetching transactions for selected date:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrevWeek = () => {
|
||||
setCurrentWeek(currentWeek.clone().subtract(1, 'week'));
|
||||
};
|
||||
|
||||
const handleNextWeek = () => {
|
||||
setCurrentWeek(currentWeek.clone().add(1, 'week'));
|
||||
};
|
||||
|
||||
const getTotalForWeek = () => {
|
||||
const weekData = getWeekData();
|
||||
const total = weekData.reduce((acc, curr) => acc + curr.amount, 0);
|
||||
return total;
|
||||
};
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
data={[{ key: 'content' }]}
|
||||
renderItem={() => (
|
||||
<View style={styles.container}>
|
||||
{data.length === 0 ? (
|
||||
<Text style={styles.noDataText}>Nessun dato disponibile</Text>
|
||||
) : (
|
||||
<>
|
||||
<Text style={styles.weekText}>{getCurrentWeekText()}</Text>
|
||||
<Text style={[styles.totalText, { color: getTotalForWeek() >= 0 ? 'green' : 'red' }]}>
|
||||
Totale: {getTotalForWeek().toFixed(2)} €
|
||||
</Text>
|
||||
<LineChart
|
||||
bezier
|
||||
data={chartData}
|
||||
width={Dimensions.get('window').width - 20} // from react-native
|
||||
height={300}
|
||||
verticalLabelRotation={30}
|
||||
yAxisLabel="€"
|
||||
chartConfig={{
|
||||
backgroundColor: '#fff',
|
||||
backgroundGradientFrom: '#000',
|
||||
backgroundGradientTo: '#000',
|
||||
decimalPlaces: 2, // optional, defaults to 2dp
|
||||
color: (opacity = 1) => `#f57242`,
|
||||
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||
style: {
|
||||
borderRadius: 10,
|
||||
},
|
||||
propsForDots: {
|
||||
r: '6',
|
||||
strokeWidth: '3',
|
||||
stroke: '#3956e6',
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 15,
|
||||
}}
|
||||
onDataPointClick={handleDataPointClick}
|
||||
/>
|
||||
|
||||
<View style={styles.buttonContainer}>
|
||||
<TouchableOpacity
|
||||
style={styles.navButton}
|
||||
onPress={handlePrevWeek}
|
||||
>
|
||||
<Text style={styles.navButtonText}>Settimana Precedente</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.navButton}
|
||||
onPress={handleNextWeek}
|
||||
>
|
||||
<Text style={styles.navButtonText}>Settimana Successiva</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Modal
|
||||
animationType="slide"
|
||||
transparent={true}
|
||||
visible={modalVisible}
|
||||
onRequestClose={() => setModalVisible(false)}
|
||||
>
|
||||
<View style={styles.centeredView}>
|
||||
<View style={styles.modalView}>
|
||||
<Text style={styles.modalTitle}>Transazioni del {selectedDate}</Text>
|
||||
<FlatList
|
||||
data={selectedTransactions}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item }) => (
|
||||
<View style={styles.transactionItem}>
|
||||
<View><Text style={styles.transactionDescription}>{item.description}</Text></View>
|
||||
<View>
|
||||
<Text style={[styles.transactionAmount, { color: item.type === 'expense' ? 'red' : 'green' }]}>
|
||||
{item.type === 'expense' ? '-' : '+'}{Math.abs(item.amount).toFixed(2)} €
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.closeButton}
|
||||
onPress={() => setModalVisible(false)}
|
||||
>
|
||||
<Text style={styles.closeButtonText}>Chiudi</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
keyExtractor={item => item.key}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginTop: 20,
|
||||
padding: 10,
|
||||
},
|
||||
buttonContainer: {
|
||||
justifyContent: 'space-between',
|
||||
flexDirection: 'row',
|
||||
marginVertical: 10,
|
||||
},
|
||||
noDataText: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
textAlign: 'center',
|
||||
marginTop: 20,
|
||||
},
|
||||
transactionsContainer: {
|
||||
},
|
||||
transactionsTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
color: '#fff',
|
||||
marginVertical: 15,
|
||||
textAlign: 'center',
|
||||
},
|
||||
transactionItem: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: 15,
|
||||
marginVertical: 5,
|
||||
borderRadius: 10,
|
||||
width: '100%',
|
||||
backgroundColor: '#1a1a1a',
|
||||
},
|
||||
transactionDate: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
transactionDescription: {
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
},
|
||||
transactionAmount: {
|
||||
color: 'red',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
centeredView: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginTop: 22,
|
||||
},
|
||||
modalView: {
|
||||
margin: 20,
|
||||
height: 500,
|
||||
backgroundColor: '#000',
|
||||
borderRadius: 20,
|
||||
borderColor: '#3c3c3c',
|
||||
borderWidth: 2,
|
||||
padding: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 15,
|
||||
textAlign: 'center',
|
||||
color: '#fff'
|
||||
},
|
||||
navButton: {
|
||||
padding: 10,
|
||||
borderRadius: 5,
|
||||
margin: 2,
|
||||
backgroundColor: '#f57242',
|
||||
},
|
||||
navButtonText: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
},
|
||||
closeButton: {
|
||||
marginTop: 20,
|
||||
padding: 10,
|
||||
borderRadius: 5,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
closeButtonText: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
},
|
||||
weekText: {
|
||||
color: '#fff',
|
||||
fontSize: 22,
|
||||
textAlign: 'center',
|
||||
paddingBottom: 20
|
||||
},
|
||||
totalText: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
marginBottom: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default VisualizzaDati;
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue