MoneyListato/components/transaction/TransactionItem.jsx
2024-11-19 02:04:30 +01:00

341 lines
11 KiB
JavaScript

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, FlatList, StyleSheet, Modal, TouchableOpacity, TextInput, Alert } from 'react-native';
import * as SQLite from 'expo-sqlite';
import { useFocusEffect } from '@react-navigation/native';
import { Picker } from '@react-native-picker/picker';
import { format } from 'date-fns';
import { it } from 'date-fns/locale';
import DateTimePicker from '@react-native-community/datetimepicker';
export default function TransactionItem() {
const [transactions, setTransactions] = useState([]);
const [modalVisible, setModalVisible] = useState(false);
const [selectedTransaction, setSelectedTransaction] = useState(null);
const [editDescription, setEditDescription] = useState('');
const [editAmount, setEditAmount] = useState('');
const [editCategory, setEditCategory] = useState('');
const [editDate, setEditDate] = useState(new Date());
const [editType, setEditType] = useState('expense');
const [showDatePicker, setShowDatePicker] = useState(false);
const loadTransactions = useCallback(async () => {
try {
const db = await SQLite.openDatabaseAsync('moneyAppDB');
const result = await db.getAllAsync('SELECT * FROM transactions ORDER BY date DESC, id DESC');
setTransactions(result);
} catch (error) {
console.error('Error fetching transactions:', error);
}
}, []);
const sortedTransactions = transactions.sort((a, b) => {
const dateA = new Date(a.date.split('-').reverse().join('-'));
const dateB = new Date(b.date.split('-').reverse().join('-'));
return dateB - dateA;
});
const groupedTransactions = sortedTransactions.reduce((acc, transaction) => {
const date = new Date(transaction.date.split('-').reverse().join('-'));
const formattedDate = format(date, 'dd MMMM yyyy', { locale: it });
if (!acc[formattedDate]) {
acc[formattedDate] = [];
}
acc[formattedDate].push(transaction);
return acc;
}, {});
useEffect(() => {
loadTransactions();
}, [loadTransactions]);
useFocusEffect(
useCallback(() => {
loadTransactions();
}, [loadTransactions])
);
const openModal = (transaction) => {
setSelectedTransaction(transaction);
setEditDescription(transaction.description);
setEditAmount(transaction.amount.toString());
setEditCategory(transaction.category);
setEditDate(new Date(transaction.date.split('-').reverse().join('-')));
setEditType(transaction.type);
setModalVisible(true);
};
const updateTransaction = async () => {
try {
const db = await SQLite.openDatabaseAsync('moneyAppDB');
await db.runAsync(
'UPDATE transactions SET description = ?, amount = ?, category = ?, date = ?, type = ? WHERE id = ?',
[editDescription, parseFloat(editAmount), editCategory, format(editDate, 'dd-MM-yyyy'), editType, selectedTransaction.id]
);
setModalVisible(false);
loadTransactions();
Alert.alert('Successo', 'Transazione aggiornata con successo');
} catch (error) {
console.error('Error updating transaction:', error);
Alert.alert('Errore', 'Impossibile aggiornare la transazione');
}
};
const deleteTransaction = async () => {
Alert.alert(
'Conferma eliminazione',
'Sei sicuro di voler eliminare questa transazione?',
[
{ text: 'Annulla', style: 'cancel' },
{
text: 'Elimina',
style: 'destructive',
onPress: async () => {
try {
const db = await SQLite.openDatabaseAsync('moneyAppDB');
await db.runAsync('DELETE FROM transactions WHERE id = ?', [selectedTransaction.id]);
setModalVisible(false);
loadTransactions();
Alert.alert('Successo', 'Transazione eliminata con successo');
} catch (error) {
console.error('Error deleting transaction:', error);
Alert.alert('Errore', 'Impossibile eliminare la transazione');
}
}
}
]
);
};
const formatDate = (dateString) => {
const [day, month, year] = dateString.split('-');
const date = new Date(`${year}-${month}-${day}`);
return format(date, 'dd MMMM yyyy', { locale: it });
};
const sortedGroupedTransactions = Object.keys(groupedTransactions)
.sort((a, b) => new Date(b.split(' ').reverse().join(' ')) - new Date(a.split(' ').reverse().join(' ')))
.reduce((acc, key) => {
acc[key] = groupedTransactions[key];
return acc;
}, {});
const renderItem = ({ item }) => (
<TouchableOpacity onPress={() => openModal(item)} style={styles.item}>
<View>
<Text style={styles.description}>{item.description}</Text>
<Text style={styles.date}>{item.date}</Text>
</View>
<Text style={[styles.amount, { color: item.type === 'expense' ? 'red' : 'green' }]}>
{item.type === 'expense' ? '-' : '+'}{Math.abs(item.amount).toFixed(2)}
</Text>
</TouchableOpacity>
);
return (
<><FlatList
data={Object.keys(groupedTransactions)}
renderItem={({ item: date }) => (
<View key={date}>
<Text style={styles.dateHeader}>{date}</Text>
<FlatList
data={groupedTransactions[date]}
renderItem={renderItem}
keyExtractor={item => item.id.toString()} />
</View>
)}
keyExtractor={item => item} /><Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(false)}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalTitle}>Dettagli Transazione</Text>
<TextInput
style={styles.input}
value={editDescription}
onChangeText={setEditDescription}
placeholder="Descrizione" />
<TextInput
style={styles.input}
value={editAmount}
onChangeText={setEditAmount}
placeholder="Importo"
placeholderTextColor="#fff"
keyboardType="decimal-pad" />
<View style={{ borderColor: 'gray', borderWidth: 1, marginBottom: 10 }}>
<Picker
selectedValue={editCategory}
style={styles.picker}
onValueChange={(itemValue) => setEditCategory(itemValue)}
>
<Picker.Item label="Spesa" value="spesa" />
<Picker.Item label="Svago" value="svago" />
<Picker.Item label="Trasporti" value="trasporti" />
<Picker.Item label="Cibo" value="cibo" />
<Picker.Item label="Varie" value="varie" />
</Picker>
</View>
<View style={{ borderColor: 'gray', borderWidth: 1, marginBottom: 10 }}>
<Picker
selectedValue={editType}
style={styles.picker}
onValueChange={(itemValue) => setEditType(itemValue)}
>
<Picker.Item label="Entrata" value="income" />
<Picker.Item label="Uscita" value="expense" />
</Picker>
</View>
<TouchableOpacity onPress={() => setShowDatePicker(true)}>
<Text style={styles.input}>{format(editDate, 'dd-MM-yyyy')}</Text>
</TouchableOpacity>
{showDatePicker && (
<DateTimePicker
value={editDate}
mode="date"
display="default"
onChange={(event, selectedDate) => {
const currentDate = selectedDate || editDate;
setShowDatePicker(false);
setEditDate(currentDate);
} } />
)}
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={updateTransaction}>
<Text style={styles.buttonText}>Aggiorna</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={deleteTransaction}>
<Text style={styles.buttonText}>Elimina</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => setModalVisible(false)}>
<Text style={styles.buttonText}>Chiudi</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal></>
);
};
const styles = StyleSheet.create({
container: {
paddingHorizontal: 10,
marginBottom: 20,
},
title: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 10,
color: '',
},
item: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 10,
marginVertical: 5,
borderRadius: 10,
backgroundColor: '#1a1a1a',
},
description: {
color: '#fff',
fontSize: 18,
fontWeight: 'bold',
},
amount: {
color: 'red',
fontSize: 16,
fontWeight: 'bold',
},
date: {
color: '#fff',
fontSize: 14,
},
centeredView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
modalView: {
margin: 20,
backgroundColor: '#000',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
modalTitle: {
color: '#fff',
fontSize: 18,
fontWeight: 'bold',
marginBottom: 15,
},
input: {
height: 60,
width: 302,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
paddingHorizontal: 15,
paddingVertical: 15,
color: '#fff',
fontSize: 16,
backgroundColor: '#1a1a1a'
},
picker: {
height: 50,
width: 300,
color: '#fff',
borderColor: 'gray',
borderWidth: 1,
backgroundColor: '#1a1a1a'
},
buttonContainer: {
paddingTop: 20,
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
},
button: {
backgroundColor: '#2196F3',
borderRadius: 20,
padding: 10,
elevation: 2,
marginTop: 10,
minWidth: 100,
},
deleteButton: {
backgroundColor: '#FF0000',
},
closeButton: {
marginTop: 20,
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
textAlign: 'center',
},
date: {
color: '#8c8c8c',
fontSize: 14,
},
dateHeader: {
fontSize: 16,
color: '#fff',
marginTop: 20,
marginBottom: 10,
marginLeft: 5,
},
});